home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Best of Shareware
/
Best of PC Windows Shareware 1.0 - Wayzata Technology (7111) (1993).iso
/
mac
/
ZIPPED
/
DOS
/
GRAPHICS
/
POVSRC.ZIP
/
MACHINE.ZIP
/
MAC.SIT
/
pov.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-24
|
106KB
|
4,127 lines
/****************************************************************************
* POV.c
*
* This file contains Macintosh-specific routines for Persistence Of Vision
* raytracer (POV-Ray.)
*
* This Macintosh version of POV-Ray was created and compiled by Jim Nitchals
* (Think 5.0) and Eduard Schwan (MPW), based very loosely on the original
* ports by Thomas Okken and David Lichtman with some help from Glenn Sugden.
*
* For bug reports regarding the Mac version specifics ONLY, go ahead and
* contact Jim Nitchals at Compuserve: 73117,3020 or America Online: JIMN8.
* Look for forum support on America Online's Mac Graphics forum Company
* Support area, or Compuserve's Computer Art (COMART) forum.
*
* from Persistence of Vision Raytracer
* Copyright 1991-1992 Persistence of Vision Team
*---------------------------------------------------------------------------
* Copying, distribution and legal info is in the file povlegal.doc which
* should be distributed with this file. If povlegal.doc is not available
* or for more information please contact:
*
* Drew Wells [POV-Team Leader]
* CIS: 73767,1244 Internet: 73767.1244@compuserve.com
* Phone: (213) 254-4041
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*/
/* Standard C headers */
#include <stdlib.h>
#include <setjmp.h>
#include "frame.h"
#include "povproto.h"
/* Macintosh-specific headers */
#include <Controls.h>
#include <Desk.h>
#include <Dialogs.h>
#include <Files.h>
#include <Memory.h>
#include <Menus.h>
#include <OSEvents.h>
#include <OSUtils.h>
#include <Packages.h>
#include <QuickDraw.h>
#include <Resources.h>
#include <Types.h>
#include <Windows.h>
#include <scrap.h>
#include <shutdown.h>
#include <sound.h>
#include <AppleEvents.h>
#include <GestaltEqu.h>
#include <Folders.h>
#include <errors.h> /* dupFNErr, etc */
#include <fonts.h>
#include <segload.h> /*UnloadSeg*/
#include <eppc.h> /* kHighLevelEvent */
#include <traps.h> /* _Unimplemented */
#ifdef applec
#include <strings.h> /*p2cstr*/
#endif
#include <string.h> /*strcpy/cat*/
#include <toolutils.h> /* BitTst, etc */
/* MPW Performance tool code */
#ifdef applec
#ifdef NEEDS_PERF
#include <perf.h>
#endif NEEDS_PERF
#endif applec
#include "SaveCmpPict.h"
#include "POVMac.h" /* includes function prototypes */
/* printf capture window */
#include "printf2window.h"
/* These #defines map Think C names into their MPW C equivalent */
#ifdef applec
#define CtoPstr c2pstr
#define PtoCstr p2cstr
#define OK ok
#define Cancel cancel
#endif applec
#define reserveMemSize 80000L /* out-of-mem reserve space */
#define _QD32Trap 0xAB03 /* 32 bit Quickdraw trap */
/* keyboard values used by ModalFilter() */
#define kReturnKey 0x0D
#define kEnterKey 0x03
#define kEscKey 0x1B
#define kTabKey 0x09
/* All dialogs have a user item #3 for outlining buttons */
#define kDefaultItem 3
/* Dialog resource IDs */
#define kdlog_P2W_INIT_ERROR 9601
#define kdlog_TOO_MANY_FILES 151
#define kMinMultiFriendly 1
#define kDefMultiFriendly 4
#define kMaxMultiFriendly 15
/* The Finder Events Suite - defined in the not-yet-existing <AERegistry.h> */
#define kAEFinderEvents 'FNDR'
#ifdef applec
/* entry point to %a5init segment, for disposal after init */
extern void _DataInit();
#ifdef NEEDS_PERF
TP2PerfGlobals ThePGlobals; /* performance globals rec */
#endif NEEDS_PERF
#endif applec
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* POV-Ray externals *-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
extern void alt_main(short argc, char **argv);
volatile extern int Stop_Flag;
extern int token_count, line_count;
extern DBL Max_Trace_Level;
extern COLOUR_MAP_ENTRY *Construction_Map;
extern int Targa_Line_Number;
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/* Externals from the text editor */
extern pascal void ScrollProc (ControlHandle theControl, short theCode);
// extern pascal void ScrollProc (ControlHandle theControl, int theCode);
extern WindowRecord wRecord;
extern WindowPtr TextEditWindow;
extern TEHandle TEH;
extern char dirty;
extern ControlHandle vScroll;
extern char window_visible;
extern Str255 theFileName;
extern short theVRefNum;
extern Cursor waitCursor;
#define PICTF_HEADER_SIZE 512 // old MacDraw PICTF header
/* Pict file header structure (after the 512 byte header) */
typedef struct
{
short picSize; // low word of size
Rect picFrame; // picture bounds
} PictFHeader, *PictFHeaderPtr;
PicHandle myPicHandle; // used by Paint_to_Picture() and MyPutPicProc()
long myPicSize; // used by Paint_to_Picture() and MyPutPicProc()
jmp_buf env;
int POV_running = 0; /* Used to determine the menu states. */
int ARGC;
char *ARGV[32], argstr[1024], *argptr;
short ourRefNum, prefsRefNum, fileResRefNum;
char targaOutName[256]; /* name of Targa output file */
PixMapHandle pm;
WindowPtr plot_window = NULL;
Ptr plot_pixmap = NULL;
Ptr undo_buffer = NULL;
Ptr undo_buffer2 = NULL;
Ptr revert_buffer = NULL;
long global_bufsize;
short undoable = 0; /* can we undo this operation? */
short backgrounding = 0; /* is the program currently backgrounded? */
short do_notify = 0; /* inform user of completed trace */
Rect plot_bounds, disp_plot_bounds;
short global_width, global_height, global_y;
int in_parse = 0; /* track malloc() and free() during parse only! */
long MyTickCount = 0; /* Time of last Event manager call */
long MyRefreshCount = 0; /* Time of last Quickdraw dither of graphic port */
int lastDrawnY = 0; /* last vertical position during previous refresh */
int WNEavailable = 0; /* Running under MultiFinder or System 7? */
int Gestalt_Available = 0; /* Gestalt available? */
int AppleEvents_Available = 0; /* Apple Events available for doing shutdown? */
int qd32_Available = 0; /* is 32 bit Quickdraw available for depth & dithering */
int ImageCompressionMgrAvailable=0; /* Is QuickTime available? */
long MultiFriendly = 0;
long ditherTime = 360;
long startupMessageTime = 0;
short display_magniFactor = 1;
Boolean doPictCompression = false;
FILE *virtual_file = 0;
FILE *savePICT_file = 0;
short virtual_pixHeight = 0;
short virtual_bufferDirty = 0;
short virtual_currentSegment = 0;
short virtual_minY = 0;
short virtual_maxY = 0;
long virtual_segSize = SWAP_SIZE;
MenuHandle myMenus[highest_menu+1];
MenuHandle mySubMenus[highest_submenu+1];
RgnHandle theUpdateRgn;
char run_flag = 0, quit_flag = 0;
EventRecord myEvent;
long prev_upd_plot;
prefs_ptr_t global_settings;
prefs_hdl_t global_settings_h;
prefs_ptr_t file_settings;
prefs_hdl_t file_settings_h;
short pause_flag = 0;
short itemHit;
short enable_return_key;
DialogPtr myDialog = NULL;
DialogPtr startupScreen = NULL;
Handle extra_dialog_RAM;
short rendered_OK;
int first_time_thru = true;
char c_theFileName[255];
long TargetTicks;
long mallocCount, mfreeCount, maxmalloc;
long *GarbagePile, *RecycledPile;
p2w_WindowPtr myp2window = NULL;
Boolean myp2windowIsUp = false;
Rect dragBounds;
/* QuickTime stuff */
ComponentInstance gtheSCComponent = NULL;
SCParams gSCDialogParams;
/* text editor undo support */
typedef struct
{
char *buffer;
char **buf_handle;
short dirty;
long byteCount, selStart, selEnd;
char reason[127];
} undoStruct;
#define max_undo 16
int undoCount;
char undo_menu_name[127], redo_menu_name[127];
int undo_key_copied;
undoStruct undo_record[max_undo+1];
undoStruct redo_record[max_undo+1];
/* Undefine the malloc and free calls now */
#undef malloc
#undef free
#undef calloc
/* NewPtr is too slow. Think's memory system is nice 'n fast. */
/* Consider using handles and locking them-- also faster than NewPtr */
void *POV_malloc(size_t size)
{
void *myptr = NULL;
TRY_TO_ALLOCATE:
if (extra_dialog_RAM != NULL)
myptr = malloc(size);
if (myptr == 0)
{
if (free_undo_memory())
goto TRY_TO_ALLOCATE;
/* if there's any other RAM we can squeeze, now's the time. */
if (extra_dialog_RAM)
{
DisposeHandle(extra_dialog_RAM);
extra_dialog_RAM = NULL;
}
}
else
if (in_parse)
{
GarbagePile[mallocCount] = (long) myptr;
if (mallocCount < maxmalloc)
mallocCount++;
}
return myptr;
}
void *POV_calloc(size_t nmemb, size_t size)
{
void *myptr = NULL;
TRY_TO_ALLOCATE:
if (extra_dialog_RAM != NULL)
myptr = calloc(nmemb, size);
if (myptr == 0)
{
if (free_undo_memory())
goto TRY_TO_ALLOCATE;
/* if there's any other RAM we can squeeze, now's the time. */
if (extra_dialog_RAM)
{
DisposeHandle(extra_dialog_RAM);
extra_dialog_RAM = NULL;
}
}
else
if (in_parse)
{
GarbagePile[mallocCount] = (long) myptr;
if (mallocCount < maxmalloc)
mallocCount++;
}
return myptr;
}
void POV_free(void *ptr)
{
if (in_parse == 0)
{
free(ptr);
return;
}
if (ptr)
{
free(ptr);
RecycledPile[mfreeCount] = (long) ptr;
if (mfreeCount < maxmalloc)
mfreeCount++;
}
}
// included in case of future inclusion by POV-Ray main
void getch(void)
{
// part of "usage" message printing in POVRay.C
}
void Collect_Garbage(void)
{
long i, j, k;
long the_item;
long *trashSorter;
in_parse = 1;
if (mallocCount == 0) return;
DisableMenus();
SetCursor(&waitCursor);
k = mallocCount;
/* malloc and mfree's are in chronological order. The first matching item
in the malloc list is always the correct one for the first occurrence in the mfree list. */
if (mfreeCount)
{
for (i=0; i<mfreeCount; i++)
{
the_item = RecycledPile[i];
trashSorter = GarbagePile;
for (j = 0; j<k; j++)
{
if (*trashSorter++ == the_item)
{
--trashSorter;
*trashSorter = 0;
goto ALREADY_FREE;
}
}
ALREADY_FREE:
Cooperate();
}
}
for (i=0; i<mallocCount; i++)
{
if (GarbagePile[i])
free((void *) GarbagePile[i]);
Cooperate();
}
printf("Done releasing memory.\n");
mallocCount = 0;
mfreeCount = 0;
*GarbagePile = 0;
*RecycledPile = 0;
EnableMenus();
SetCursor(&qd.arrow);
}
void restore_state(void)
{
rendered_OK = 0;
longjmp(env, 1);
}
int first_time_called(void)
{
int a;
a = first_time_thru;
first_time_thru = false;
return (a);
}
#ifdef NEEDS_PERF
void startPerf(void)
{
/* Initialize the performance globals */
ThePGlobals = nil;
if (!InitPerf(&ThePGlobals,
4, /* ms */
8, /* bytes */
true, /* measure ROM code */
true, /* measure application code */
(StringPtr)"\pCODE", /* segments to measure */
0, /* Let the performance tools calculate the ROM id */
(StringPtr)"\p", /* Let the performance tools find the ROM name */
true, /* measure RAM? */
0, /* low RAM address */
0x0FFFFF, /* high RAM address */
16 /* RAM bucket size */
))
{
SysBeep(4); /* error */
// displayDialog(rErrorID,"Errors starting Performance Dump!");
// exit(1); /* error */
}
}
void doPerf(short perfFlag)
{
PerfControl(ThePGlobals, perfFlag); /* turn on/off measurements */
} /* doPerf */
void stopPerf(void)
{
/* Write the performance raw data into a file */
/* NOTE: IN MPW 3.2, YOU WILL CRASH HORRIBLY IF YOU TURN ON/OFF Perf TWICE! */
/* doPerf(false); /* make sure everything is turned off */
if (PerfDump(ThePGlobals, (StringPtr)"\pPOVPerf.out", true, 80) )
{
SysBeep(4); /* error */
// displayDialog(rErrorID,"Errors while saving Performance Dump!");
}
TermPerf(ThePGlobals); /* clean up */
}
#endif NEEDS_PERF
void get_WindowPos(WindowPtr theWindow, Rect *theRect)
{
Rect windRect;
windRect = theWindow->portRect;
// yah, but where is it really?
SetPort(theWindow);
LocalToGlobal((Point*)&windRect.top);
LocalToGlobal((Point*)&windRect.bottom);
*theRect = windRect;
}
void forceRectOnScreen(Rect *aGlobalRect)
{
long area;
long foundArea;
GDHandle aDevice;
GDHandle foundDevice;
Rect aDeviceRect;
Rect intersectRect;
/* Use main device as default choice, in case no match found */
foundDevice = GetMainDevice();
aDeviceRect = (**foundDevice).gdRect;
SectRect(aGlobalRect, &aDeviceRect, &intersectRect);
foundArea = 0;
for (aDevice = GetDeviceList(); aDevice; aDevice = GetNextDevice(aDevice))
{
/* If we found an active screen device that intersects some of the rect.. */
aDeviceRect = (**aDevice).gdRect;
if (TestDeviceAttribute(aDevice, screenDevice)
&& TestDeviceAttribute(aDevice, screenActive)
&& SectRect(aGlobalRect, &aDeviceRect, &intersectRect))
{
/* find out how much it intersects */
area = (intersectRect.right - intersectRect.left) *
(intersectRect.bottom - intersectRect.top);
/* if intersects more than the last device of intersection, use this instead */
/* this therefore finds the screen of greatest intersection */
if (area > foundArea)
{
foundDevice = aDevice;
foundArea = area;
}
}
}
/* OK, we have now travelled through all the devices, and 'foundDevice' */
/* will have the best device to use, or the main device if there was */
/* no intersecting screens at all.. Make sure it fits on the screen */
/* If there is not enough area showing, or top of rect is off screen.. */
/* then move the window to better position on 'foundDevice' */
if ( (foundArea < 200) || (aGlobalRect->top < (**foundDevice).gdRect.top) )
{
/* adjust gdRect to size of aGlobalRect, & offset it a little */
aDeviceRect = (**foundDevice).gdRect;
OffsetRect(&aDeviceRect, 10, 40);
aDeviceRect.right = aDeviceRect.left + (aGlobalRect->right - aGlobalRect->left);
aDeviceRect.bottom = aDeviceRect.top + (aGlobalRect->bottom - aGlobalRect->top);
/* Return this rect as the one to use */
*aGlobalRect = aDeviceRect;
}
} // forceRectOnScreen
short trapAvailable(short tNumber, TrapType tType, SysEnvRec *seRec)
{
if (
(tType == (unsigned char) ToolTrap) &&
(seRec->machineType > envMachUnknown) &&
(seRec->machineType < envMacII)
)
{ /* it's a 512KE, Plus, or SE */
tNumber = tNumber & 0x03FF;
if (tNumber > 0x01FF) /* which means the tool traps */
tNumber = _Unimplemented; /* only go to 0x01FF */
}
return (NGetTrapAddress(tNumber, tType)
!= NGetTrapAddress(_Unimplemented, ToolTrap));
} /*trapAvailable()*/
pascal void outlineDefaultButton(DialogPtr theDialog, short theItem)
{
PenState SavePen;
short itemType;
Handle itemHandle;
Rect dispRect;
#pragma unused (theItem)
GetPenState(&SavePen);
/* use 'ok' (#1) item's rectangle */
GetDItem(theDialog, OK, &itemType, &itemHandle, &dispRect);
SetPort(theDialog);
PenSize(3, 3);
InsetRect(&dispRect, -4, -4);
FrameRoundRect(&dispRect, 16, 16);
SetPenState(&SavePen);
} // outlineDefaultButton
/* Grabs the ControlHandle for the item in the dialog box */
ControlHandle GrabDItemHandle(DialogPtr theDialog, short theGetItem)
{
short itemtype;
Rect itemrect;
Handle tempHandle;
GetDItem(theDialog, theGetItem, &itemtype, &tempHandle, &itemrect);
return((ControlHandle)tempHandle);
} // GrabDItemHandle
/* Sets dialog's #1 item's display proc to draw outline */
void SetupDefaultButton(DialogPtr theDialog)
{
short itemtype;
Rect itemrect;
Handle tempHandle;
/* Set up User item (always #3) to display a border around OK button (#1) */
GetDItem(theDialog, kDefaultItem, &itemtype, &tempHandle, &itemrect);
SetDItem(theDialog, kDefaultItem, itemtype, (Handle)&outlineDefaultButton, &itemrect);
enable_return_key = 1; // enable the Return key for "OK" by default.
} // SetupDefaultButton
pascal Boolean ModalFilter(DialogPtr theDialog, EventRecord *theDialogEvent, short *theDialogItem)
{
WindowPtr tempGP;
char theKey;
long tilticks;
Boolean returnVal = false; // not yet handled
/* remember where we parked */
GetPort(&tempGP);
SetPort(theDialog);
/* Deal with KeyDowns */
if ((theDialogEvent->what == keyDown) || (theDialogEvent->what == autoKey))
{
theKey = theDialogEvent->message & charCodeMask;
/* Do filtering for <ESC> and <CR> as OK and Cancel, per Human Interface guidelines. */
switch (theKey)
{
case kEnterKey:
/* Make the Enter key identical to the Return key! */
/* Mask out the Enter key, and OR in the Return key */
theDialogEvent->message = (theDialogEvent->message & ~charCodeMask) | kReturnKey;
case kReturnKey:
if (enable_return_key)
{
/* This filters for Return or Enter as item 1, and Esc as item 2 */
*theDialogItem = OK; /* change whatever the current item is to the OK item */
/* now we need to invert the button */
HiliteControl(GrabDItemHandle(theDialog, OK), inButton);
Delay(8, &tilticks); /* wait about 8 ticks so they can see it */
HiliteControl(GrabDItemHandle(theDialog, ok), false);
returnVal = true;
}
break;
/* This filters the escape key the same as item 2 (the canx button, usually ) */
case kEscKey:
*theDialogItem = Cancel; /* pretend the cancel button was hit */
HiliteControl(GrabDItemHandle(theDialog, Cancel), inButton);
Delay(8, &tilticks); /* wait about 8 ticks so they can see it */
HiliteControl(GrabDItemHandle(theDialog, Cancel), false);
returnVal = true;
break;
} // switch
} // if keydown
SetPort(tempGP);
return(returnVal);
} // ModalFilter
OSErr GotRequiredParams(AppleEvent *theAppleEvent)
{
DescType typeCode;
Size actualSize;
OSErr err;
err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
&typeCode, NULL, 0, &actualSize); /* NULL ok here; need only function result */
if (err == errAEDescNotFound)
// we got all the required params: all is ok
return noErr;
else if (err == noErr)
// found one left behind: error!
return errAEEventNotHandled;
else
// some other oddity
return err;
} // GotRequiredParams
pascal OSErr HandleOapp (AEDescList *aevt, AEDescList *reply, long refCon)
{
#pragma unused (reply,refCon)
OSErr anError;
/* We don't normally expect any parms, but check in case the client requires any */
anError = GotRequiredParams(aevt);
if (!anError)
DoFile_New();
/* if splash screen is up, pull it back to the front! */
if (startupScreen)
{
SelectWindow(startupScreen);
DrawDialog(startupScreen);
}
return anError;
}
pascal OSErr HandleOdoc (AEDescList *aevt, AEDescList *reply, long refCon)
{
#pragma unused (reply,refCon)
OSErr anError;
AEDesc fileListDesc;
DescType actualType;
long actualSize;
AEKeyword actualKeyword;
FSSpec oneFile;
long numFiles;
long index;
/* The "odoc" and "pdoc" messages contain a list of aliases as the direct paramater. */
/* This means that we'll need to extract the list, count the list's elements, and */
/* then process each file in turn. Return any errors to the client. */
/* Extract the list of aliases into fileListDesc */
anError = AEGetParamDesc(aevt, keyDirectObject, typeAEList, &fileListDesc);
/* Make sure that's all we're supposed to do */
if (!anError)
anError = GotRequiredParams(aevt);
/* Count the list elements */
if (!anError)
anError = AECountItems(&fileListDesc, &numFiles);
/* This application is rather limited for now, it just */
/* wants ONE document. Err if more! */
if (!anError && (numFiles > 1))
{
displayDialog(kdlog_TOO_MANY_FILES, "", numFiles);
numFiles = 1; /* force the issue! */
}
/* now get each file from the list and process it. */
/* Even though the event contains a list of aliases, the Apple Event Manager */
/* will convert each alias to an FSSpec if we ask it to. */
for (index = 1; (index <= numFiles) && !anError; index++)
{
/* Pull the Nth file out of the aevt list */
anError = AEGetNthPtr( &fileListDesc, index, typeFSS, &actualKeyword,
&actualType, (Ptr)&oneFile, sizeof(oneFile), &actualSize);
/* Open the File here */
if (!anError)
{
OpenTextFile(oneFile.name, oneFile.vRefNum, oneFile.parID, true/*UseDirID*/);
}
}
/* All done with the list, throw it away */
if (!anError)
anError = AEDisposeDesc(&fileListDesc);
/* if splash screen is up, pull it back to the front! */
if (startupScreen)
{
SelectWindow(startupScreen);
DrawDialog(startupScreen);
}
return anError;
}
pascal OSErr HandleQuit (AEDescList *aevt, AEDescList *reply, long refCon)
{
#pragma unused (reply,refCon)
OSErr anError;
/* We don't normally expect any parms, but check in case the client requires any */
anError = GotRequiredParams(aevt);
Stop_Flag = quit_flag = TRUE;
return anError;
}
void Install_AppleEvents(void)
{
OSErr err;
long result;
if (Gestalt_Available)
{
err = Gestalt(gestaltAppleEventsAttr, &result);
if (err == noErr) {
AppleEvents_Available = TRUE;
(void)AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
(EventHandlerProcPtr)HandleOapp, 0, false);
(void)AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
(EventHandlerProcPtr)HandleOdoc, 0, false);
(void)AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
(EventHandlerProcPtr)HandleOdoc, 0, false); /* do "Print" as Open */
(void)AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
(EventHandlerProcPtr)HandleQuit, 0, false);
}
}
}
void SendQuit(void)
{
OSErr myErr;
OSType theSignature;
AppleEvent myAEvt, myReturnEvt;
AEAddressDesc myServerAddress;
/* Still not working..! */
theSignature = 'MACS';
myErr = AECreateDesc(typeApplSignature, (Ptr)&theSignature, 4, &myServerAddress);
if (!myErr)
myErr = AECreateAppleEvent(kAEFinderEvents, // Event Class
kAEShutDown, // Event ID
&myServerAddress, // Target Adr
kAutoGenerateReturnID, // Return aevt ID
kAnyTransactionID, // Trans ID
&myAEvt); // fill me in
if (!myErr)
myErr = AESend(&myAEvt,
&myReturnEvt,
kAENoReply, // send mode
kAENormalPriority, // send priority
kNoTimeOut, // N timeout ticks
NULL, // idleProcPtr
NULL); // EventFilterProcPtr
/* clean up before we die :-) */
if (!myErr)
myErr = AEDisposeDesc(&myServerAddress);
}
/* Returns the compiler name this code was compiled with */
void GetCompilerNamePString(Str31 versionString)
{
versionString[0] = '\0';
#ifdef applec
pStrCopy("\pApple's MPW C", versionString);
#endif applec
#ifdef THINK_C
pStrCopy("\pSymantec's Think C", versionString);
#endif THINK_C
}
/* Returns the version string in the application's version resource */
void GetAppVersionPString(short versID, Str31 versionString)
{
VersRecHndl versHandle; // VersRecHndl declared in MPW's <files.h>
/* Get the resource string from app, 'vers' versID (1 or 2) resource! */
versionString[0] = '\0';
versHandle = (VersRecHndl)GetResource('vers',versID);
if (versHandle)
pStrCopy((**versHandle).shortVersion, versionString);
}
void displayDialog(short dlogID, char * s, short err)
{
short itemHit;
DialogPtr dlogp;
char numstr[10];
SysBeep(2);
InitCursor();
/* convert error string to P-style */
if (s)
c2pstr(s);
/* see if there is an error number */
numstr[0] = '\0';
if (err)
NumToString(err,numstr);
ParamText(numstr, s, "", "");
dlogp = GetNewDialog(dlogID, (Ptr)0L, (WindowPtr)-1L);
/* "default" the OK button */
SetupDefaultButton(dlogp);
if (dlogp)
{
ModalDialog(0, &itemHit);
DisposDialog(dlogp);
}
} /*displayDialog*/
void error_dialog(int dialognum)
{
DialogPtr dlgHold; /* allow a single level of dialog recursion */
/* this cheap hack guarantees enough available RAM to show the error and not crash. */
if (extra_dialog_RAM)
{
DisposeHandle(extra_dialog_RAM);
extra_dialog_RAM = 0;
}
UseResFile(ourRefNum);
dlgHold = myDialog;
SetCursor(&qd.arrow); /* it could still be a text cursor! */
myDialog = GetNewDialog(dialognum, NULL, (WindowPtr) -1);
if (myDialog)
{
/* "default" the OK button */
SetupDefaultButton(myDialog);
do {
ModalDialog(NULL, &itemHit);
} while (itemHit != 1);
DisposDialog(myDialog);
itemHit = -1; /* don't send spurious item # to other dialogs! */
}
myDialog = dlgHold;
if (FreeMem() > reserveMemSize)
extra_dialog_RAM = NewHandle(reserveMemSize);
}
/* --- These are required routines from machine.h --- */
void display_finished(void)
{
}
void display_close(void)
{
}
void open_virtual(void)
{
int err;
if (virtual_file == NULL)
{
virtual_file = fopen("POV-Ray.imageTemp","wb+");
err = ferror(virtual_file);
}
virtual_currentSegment = -1;
virtual_bufferDirty = 0;
virtual_minY = 32767;
virtual_maxY = 0;
virtual_pixHeight = virtual_segSize / (global_width * 4);
}
void delete_virtual(void)
{
int i;
if (virtual_file)
{
fclose (virtual_file);
virtual_file = NULL;
}
i = remove("POV-Ray.imageTemp"); // Thanks Eduard (any time, I got the space :-))
}
void dispose_virtual(void)
{
Handle h;
if (plot_pixmap)
{
h = RecoverHandle(plot_pixmap);
HUnlock(h);
DisposHandle(h);
plot_pixmap = NULL;
undoable = 0;
}
if (undo_buffer)
DisposePtr(undo_buffer);
if (undo_buffer2)
DisposePtr(undo_buffer2);
if (revert_buffer)
DisposePtr(revert_buffer);
undo_buffer = 0;
undo_buffer2 = 0;
revert_buffer = 0;
delete_virtual();
virtual_minY = 32767;
}
void swap_virtual_segment (short y)
{
int i;
if ( virtual_file && ((y < virtual_minY) || (y >= virtual_maxY)) )
{
if (virtual_bufferDirty && (virtual_currentSegment >= 0))
{
fseek(virtual_file, (virtual_currentSegment * virtual_segSize), SEEK_SET);
if ( fwrite((char *) plot_pixmap, virtual_segSize, 1, virtual_file) != 1)
{
dispose_virtual();
return;
}
}
virtual_currentSegment = (int) (y / virtual_pixHeight);
virtual_minY = virtual_currentSegment * virtual_pixHeight;
virtual_maxY = (virtual_currentSegment + 1) * virtual_pixHeight;
fseek(virtual_file, (virtual_currentSegment * virtual_segSize), SEEK_SET);
i = fread((char *) plot_pixmap, virtual_segSize, 1, virtual_file);
virtual_bufferDirty = 0;
}
}
void display_init(int width, int height)
{
long *p, *q, pmsize, i;
Handle h;
Rect brect;
int insuff_flag;
global_width = width;
global_height = height;
global_bufsize = 4L * (long) width * (long) height;
global_y = 0;
lastDrawnY = 0;
if (plot_window)
{
DisposeWindow(plot_window);
plot_window = NULL;
}
dispose_virtual(); /* also disposes all old Pixmaps */
SetRect(&plot_bounds, 0, 0, width, height);
SetRect(&disp_plot_bounds, 0, 0, width * display_magniFactor, height * display_magniFactor);
pmsize = 4L * width * height;
virtual_bufferDirty = 0;
if ((pmsize < ((FreeMem() - virtual_segSize) * 2 / 5)) || (pmsize < virtual_segSize))
h = NewHandle(pmsize);
else
h = 0;
if (h)
{
MoveHHi(h);
HLock(h);
plot_pixmap = *h;
q = (long *) ((long) plot_pixmap + pmsize);
for (p = (long *) plot_pixmap; p < q; *p++ = -1); /* fill to white */
(*pm)->bounds = plot_bounds;
(*pm)->rowBytes = width * 4 | 0x8000;
(*pm)->baseAddr = plot_pixmap;
ditherTime = 600; /* 10 seconds between re-dithers */
}
else
{
open_virtual();
SetRect(&plot_bounds, 0, 0, width, virtual_pixHeight);
if (virtual_file)
h = NewHandle(virtual_segSize);
ditherTime = 7200; /* 2 minutes between re-dithers */
insuff_flag = 133;
if (h)
{
insuff_flag = 139;
MoveHHi(h);
HLock(h);
plot_pixmap = *h;
(*pm)->bounds = plot_bounds;
(*pm)->rowBytes = width * 4 | 0x8000;
(*pm)->baseAddr = plot_pixmap;
q = (long *) ((long) plot_pixmap + virtual_segSize);
for (p = (long *) plot_pixmap; p < q; *p++ = -1); /* fill to white */
printf("Creating Virtual Screen Buffer..\n");
for (i=0; i < global_height; i++)
{
virtual_bufferDirty = 1;
swap_virtual_segment (i);
}
swap_virtual_segment (0); /* swap in segment 0 */
if (virtual_file == NULL)
dispose_virtual();
}
else
dispose_virtual;
/* if we can't allocate 64K, things are REALLY up the creek */
if (virtual_file == NULL)
error_dialog(insuff_flag);
}
if (display_magniFactor)
{
brect = disp_plot_bounds;
OffsetRect(&brect, file_settings->imageWind_pos.left, file_settings->imageWind_pos.top);
forceRectOnScreen(&brect);
plot_window = NewCWindow(NULL, &brect, theFileName, true, noGrowDocProc,
(WindowPtr) -1L, false, 0);
}
SetCursor(&qd.arrow); /* it could still be a text cursor from the console */
}
void Cooperate(void)
{
if (TICKS > (MyTickCount+MultiFriendly))
{
MacDawdle();
// Don't start the clock again until after all other applications get their shot in.
MyTickCount = TICKS;
}
}
void display_plot (int x, int y,
unsigned char Red, unsigned char Green, unsigned char Blue)
{
RGBColor c;
unsigned char *pptr;
Rect myInvalRect, magniRect;
long pport_y;
int mr_y;
global_y = y;
if (plot_pixmap)
{
if (virtual_file)
{
swap_virtual_segment(y);
pport_y = y - virtual_minY; /* Y offset within current virtual segment */
virtual_bufferDirty = TRUE;
if (virtual_file == NULL)
error_dialog(141);
}
else
pport_y = y;
pptr = (unsigned char *)
((long) plot_pixmap + 4L * ((long) plot_bounds.right * pport_y + (long) x));
*pptr++ = 0;
*pptr++ = Red;
*pptr++ = Green;
*pptr = Blue;
}
if (plot_window)
{
SetPort(plot_window);
c.red = (short) Red * 256 ;
c.green = ((short) Green) * 256 ;
c.blue = ((short) Blue) * 256 ;
if (display_magniFactor == 1)
SetCPixel(x, y, &c);
else
{
mr_y = (global_y * display_magniFactor);
magniRect.top = mr_y;
magniRect.bottom = mr_y + display_magniFactor;
magniRect.left = x * display_magniFactor;
magniRect.right = (x+1) * display_magniFactor;
RGBForeColor(&c);
PaintRect(&magniRect);
ForeColor(blackColor);
}
if ((TICKS > (MyRefreshCount + ditherTime)) && (backgrounding == 0))
{
if (y > (lastDrawnY + 1))
{
if (file_settings->ditherPaint)
{
myInvalRect.top = 0;
myInvalRect.bottom = (y + 1) * display_magniFactor;
myInvalRect.left = 0;
myInvalRect.right = global_width * display_magniFactor;
}
else
{
myInvalRect.top = (lastDrawnY - 1) * display_magniFactor;
myInvalRect.bottom = (y + 1) * display_magniFactor;
myInvalRect.left = 0;
myInvalRect.right = global_width * display_magniFactor;
}
SetPort (plot_window);
InvalRect(&myInvalRect);
MacDawdle();
lastDrawnY = y;
MyRefreshCount = TICKS;
}
}
}
}
void paint_whole_window(void)
{
BitMap bmap;
short myMode, i;
Rect my_bounds;
if (plot_window)
{
if (plot_pixmap)
{
bmap.baseAddr = (Ptr) pm;
bmap.rowBytes = 0xC000;
bmap.bounds = plot_bounds;
if ((file_settings->ditherPaint) && (qd32_Available))
myMode = ditherCopy;
else
myMode = srcCopy;
if (virtual_file)
for (i=0; i < global_height; i = i + virtual_pixHeight)
{
swap_virtual_segment (i);
my_bounds.top = (i * display_magniFactor);
my_bounds.bottom = my_bounds.top + (virtual_pixHeight * display_magniFactor);
/* don't worry about the bounds, the clipping region of the window will stop
us from drawing past the bottom */
my_bounds.left = 0;
my_bounds.right = global_width * display_magniFactor;
CopyBits(&bmap, &plot_window->portBits, &plot_bounds, &my_bounds,
myMode, NULL);
}
else
CopyBits(&bmap, &plot_window->portBits, &plot_bounds, &disp_plot_bounds,
myMode, NULL);
}
}
}
pascal void MyPutPicProc( char *dataPtr, short byteCount)
{
int myByteCount;
myByteCount = byteCount;
myPicSize += byteCount;
if (savePICT_file)
{
if (fwrite( dataPtr, 1, myByteCount, savePICT_file) != myByteCount)
{
fclose (savePICT_file);
savePICT_file = 0;
}
}
// we have to keep the picture handle header updated for Quickdraw!
if (myPicHandle)
(**myPicHandle).picSize = myPicSize;
}
void paint_to_picture(short do_disk_buffer)
{
BitMap bmap;
short myMode, i;
OSErr anError;
Rect my_bounds, myPicRect;
CGrafPort myCGrafPtr;
GrafPtr oldGrafPtr;
PictFHeader myPictFHeader;
CQDProcs myQDProcs;
anError = noErr;
if (plot_pixmap)
{
GetPort(&oldGrafPtr);
OpenCPort (&myCGrafPtr);
SetPort ((GrafPtr)&myCGrafPtr);
PortSize (global_width, global_height);
myPicRect.top = 0;
myPicRect.bottom = global_height;
myPicRect.left = 0;
myPicRect.right = global_width;
ClipRect(&myPicRect);
if (do_disk_buffer)
{
SetStdCProcs ((CQDProcsPtr) &myQDProcs);
myQDProcs.putPicProc = (Ptr) MyPutPicProc;
myCGrafPtr.grafProcs = (CQDProcsPtr) &myQDProcs;
// write the PICT header to the file
myPicSize = sizeof(myPictFHeader);
myPictFHeader.picSize = myPicSize; // accumulated later in MyPutPicProc()..
myPictFHeader.picFrame = myPicRect;
i = fwrite (&myPictFHeader, 1, sizeof(myPictFHeader), savePICT_file);
anError = ferror(savePICT_file);
}
if (!anError)
{
/* insure myPicHandle null, 'cause MyPutPicProc will be called in OpenPicture! */
myPicHandle = NULL;
myPicHandle = OpenPicture (&myPicRect);
anError = QDError();
}
bmap.baseAddr = (Ptr) pm;
bmap.rowBytes = 0xC000; // flag for PixMap
if ((file_settings->ditherPaint) && (qd32_Available))
myMode = ditherCopy;
else
myMode = srcCopy;
if (!anError)
{
if (virtual_file)
for (i=0; (i <= global_height) && !anError; i = i + virtual_pixHeight)
{
swap_virtual_segment (i);
my_bounds.top = i;
// NOTE, JIM! (next source line)
// By doing a CopyBits of the last rect in full, the whole rect of pixels _does_
// get written to the PICT file, even though not all the scan lines are valid..
// this doesn't hurt anything, just makes the file a little bigger than it needs to be,
// since the extra lines will get clipped on playback. However, since plot_bounds is
// global, it would be icky to temporarily change its bottom along with my_bounds so
// as to only write the necessary lines.. maybe later. :-)
my_bounds.bottom = i + virtual_pixHeight;
my_bounds.left = 0;
my_bounds.right = global_width;
CopyBits(&bmap, (BitMap *)&myCGrafPtr.portPixMap, &plot_bounds, &my_bounds,
myMode, NULL);
anError = QDError();
}
else
{
CopyBits(&bmap, (BitMap *)&myCGrafPtr.portPixMap, &plot_bounds, &plot_bounds,
myMode, NULL);
anError = QDError();
}
}
/* write end-of-picture */
if (!anError)
{
ClosePicture();
anError = QDError();
}
if (!anError)
{
if (do_disk_buffer)
{
/* don't call us anymore! */
SetStdCProcs((CQDProcsPtr) &myQDProcs);
/* move back to pic header again */
fflush(savePICT_file);
fseek(savePICT_file, PICTF_HEADER_SIZE, SEEK_SET);
anError = ferror(savePICT_file);
/* update the PICT header in the file (with now-true picSize field..) */
if (!anError)
{
myPictFHeader.picSize = myPicSize;
i = fwrite (&myPictFHeader, 1, sizeof(myPictFHeader), savePICT_file);
anError = ferror(savePICT_file);
}
}
else
{
ZeroScrap();
HLock((Handle) myPicHandle);
myPicSize = GetHandleSize((Handle) myPicHandle);
PutScrap (myPicSize, 'PICT', (Ptr) *myPicHandle);
myPicSize = UnloadScrap();
HUnlock((Handle) myPicHandle);
}
} // if !error
/* close up shop */
CloseCPort(&myCGrafPtr);
SetPort(oldGrafPtr);
if (myPicHandle)
DisposeHandle((Handle) myPicHandle);
/* oh yeah, check for errors */
if (anError)
{
if (savePICT_file)
{
fclose (savePICT_file);
savePICT_file = 0;
}
SysBeep(4);
}
} // if plot_pixmap..
} // paint_to_picture()
/* Write the Pixmap as a PICT file */
void saveOutputFile(int getName)
{
SFReply reply;
Point where;
char cFname[256];
char filler[PICTF_HEADER_SIZE];
int i;
FInfo myFileInfo;
FSSpec fsFile;
Rect myPicRect;
for (i=0; i<PICTF_HEADER_SIZE; i++)
filler[i] = 0;
strcpy (cFname, c_theFileName);
if (strstr(cFname,".POV") || strstr(cFname,".pov"))
{
i = strlen(cFname);
cFname[i - 4] = 0;
}
strcat (cFname, ".PICT");
if (getName)
{
CtoPstr(cFname);
where.h = where.v = 82;
SFPutFile (where, "\pSave PICT file as╔", cFname, NULL, &reply);
}
else
{
strcpy ((char *) reply.fName,cFname);
CtoPstr(reply.fName);
reply.vRefNum = theVRefNum;
reply.good = TRUE;
}
if (reply.good)
{
PtoCstr(reply.fName);
SetVol(NULL, reply.vRefNum);
savePICT_file = fopen((char *) reply.fName,"wb");
if (savePICT_file)
{
i = fwrite (&filler, 1, PICTF_HEADER_SIZE, savePICT_file);
paint_to_picture(TRUE);
if (savePICT_file)
{
fclose (savePICT_file);
savePICT_file = 0;
CtoPstr(reply.fName);
// real hokey temporary hack to only allow compression if option key down.
// NOTE: I did it this way, because we will use the doPictCompression flag later
// when we read the compression checkbox option from the file/app prefs dialog.
/* TEMPORARY way to see if user wants compression */
if (myEvent.modifiers & optionKey)
doPictCompression = true;
else
doPictCompression = false;
/* If QuickTime is around & user wants to squish the picture, ask user how to squish it */
if (ImageCompressionMgrAvailable && doPictCompression)
{
myPicRect.top = 0;
myPicRect.bottom = global_height;
myPicRect.left = 0;
myPicRect.right = global_width;
i = FSMakeFSSpec(reply.vRefNum, 0, reply.fName, &fsFile);
if (!i)
if (PromptForCompressionStyle(gtheSCComponent, &gSCDialogParams, &fsFile))
i=CompressPictF(&gSCDialogParams, &fsFile);
// not yet tested and working, but leave in for later..
// /* stick a preview resource on it too */
// if (!i)
// i = AppendFilePreview2PictF(&fsFile);
// not yet tested and working, but leave in for later..
// /* Add System 7 custom icons of the image itself to the file */
// if (!i)
// i = AppendFinderIcons2PictF(&fsFile, &myPicRect, eAFI_ShrinkWholeImage);
}
i = GetFInfo (reply.fName, reply.vRefNum, &myFileInfo);
if (i==0)
{
myFileInfo.fdType = 'PICT';
myFileInfo.fdCreator = 'ttxt';
i = SetFInfo (reply.fName, reply.vRefNum, &myFileInfo);
}
}
else
error_dialog(140);
}
}
}
/* --- And now for the real Mac stuff --- */
char *PrintTime()
{
static Str255 t;
unsigned long secs;
GetDateTime(&secs);
IUTimeString(secs, true, t);
return (char *) t;
}
void call_main(int argc, char *argv[])
{
if (setjmp(env) == 0)
{
POV_running = 1;
/* deallocate any previous windows */
if (plot_window)
{
DisposeWindow(plot_window);
plot_window = NULL;
}
dispose_virtual(); /* also disposes all old Pixmaps */
MyTickCount = TICKS;
rendered_OK = 1; /* presume that rendering will finish OK */
printf("\n");
Collect_Garbage();
Max_Trace_Level = 5.0;
token_count = 0;
line_count = 0;
Construction_Map = NULL;
Targa_Line_Number = 0;
alt_main(argc, argv);
if (rendered_OK)
ChangeTargaType(); /* change type and creator of the Targa output file */
if (plot_window)
{
SetPort (plot_window);
InvalRect (&disp_plot_bounds);
}
}
POV_running = 0;
run_flag = 0;
}
void AddArg(const char *s)
{
ARGV[ARGC++] = argptr;
while (*argptr++ = *s++);
}
void PinValue(short *x, short a, short b)
{
if (*x < a)
*x = a;
else
if (*x > b)
*x = b;
}
OSErr OpenPrefsFile(void)
{
long theResponse; /* For call to Gestalt */
OSErr errCode;
long prefs_dirID;
short prefs_volNum;
/* default in case neither FindFolder nor SysEnvirons can help locate the Preference Folder */
prefs_dirID = 0;
prefs_volNum = 0;
errCode = -1;
if (Gestalt_Available)
{
/* Find the preferences folder */
errCode = Gestalt(gestaltFindFolderAttr, &theResponse);
if (errCode == noErr && (BitTst((Ptr)&theResponse, 31 - gestaltFindFolderPresent)))
errCode = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
&prefs_volNum, &prefs_dirID);
}
if (errCode)
{
SysEnvRec theWorld;
/* Error locating the preferences folder, so use the blessed folder */
if ((errCode = SysEnvirons(1, &theWorld)) == noErr)
prefs_volNum = theWorld.sysVRefNum;
else
/* Had a problem with SysEnvirons, try the default volume */
prefs_volNum = 0;
prefs_dirID = 0;
}
/* Create the prefs file. If it's already created, no need to create the resource fork. */
if ((errCode = HCreate(prefs_volNum, prefs_dirID, "\pPOV-Ray Prefs",
kAppSignature, 'SETT')) == noErr)
{
HCreateResFile(prefs_volNum, prefs_dirID, "\pPOV-Ray Prefs");
errCode = ResError();
}
/* Return an error code */
if (errCode == dupFNErr) /* file's already created? Not an error. */
errCode = noErr;
if (errCode == noErr)
{
prefsRefNum = HOpenResFile(prefs_volNum, prefs_dirID, "\pPOV-Ray Prefs",
fsRdWrPerm);
if (prefsRefNum == -1)
errCode = -1;
if (ResError())
errCode = ResError();
}
return errCode;
}
void Write_Our_Prefs(void)
{
ChangedResource((Handle) global_settings_h);
WriteResource((Handle) global_settings_h);
if (ResError())
{
error_dialog(144);
global_settings_h = 0;
exit_handler();
}
UpdateResFile(prefsRefNum);
}
void goto_line(short line_to_go)
{
short i;
short line_counter = 1,
mySelStart = -1,
mySelEnd = -1;
Boolean foundStart = false;
short theMaxLength = (**TEH).teLength-1;
char *myptr = *(**TEH).hText;
/* (Line 1 is a special case, of course!) */
if (line_to_go <= 1)
{
mySelStart = 0;
foundStart = true;
}
/* Find start and end of line */
for (i = 0; i < theMaxLength; i++)
if (myptr[i] == 0x0d)
if (!foundStart)
{ /* still looking for start of the line */
line_counter += 1;
if (line_counter == line_to_go)
{
mySelStart = i + 1;
foundStart = true;
}
}
else
{ /* now we found the end of the line */
mySelEnd = i + 1;
break;
}
/* Beep if we found no start of line */
if ((mySelStart < 0) && (line_to_go > 1))
{ /* Hmm, didn't find it! */
mySelStart = 0;
mySelEnd = 0;
SysBeep(4);
}
/* if no end of line found, ASSUME it is last line of file */
if (mySelEnd < mySelStart)
mySelEnd = theMaxLength;
/* Set up TE with selection */
(**TEH).selStart = mySelStart;
(**TEH).selEnd = mySelEnd;
/* show them that we're not in Kansas anymore! */
ShowSelect();
}
#define kItem_LineNum 4
void choose_goto_line(void)
{
short i, dummyInt, remember_Opts, line_to_go;
Rect displayRect;
ControlHandle cntl[31];
char s1[256];
HiliteMenu(0);
DisableItem(myMenus[1], 1); /* about box */
DisableItem(myMenus[fmn_ID], 0); /* File menu */
DisableItem(myMenus[edmn_ID], edmn_undo); /* Undo */
do_notify = 0; /* in case dialog was selected before some notification completed */
line_to_go = 1; /* for now */
UseResFile(ourRefNum);
myDialog = GetNewDialog(150, NULL, (WindowPtr) -1);
remember_Opts = 0;
for (i = 1; i <= 4; i++)
GetDItem(myDialog, i, &dummyInt, (Handle *) &cntl[i], &displayRect);
sprintf(s1, "%d", line_to_go);
SetIText((Handle) cntl[kItem_LineNum], CtoPstr(s1) );
SelIText(myDialog, kItem_LineNum, 0, 32767);
/* "default" the OK button */
SetupDefaultButton(myDialog);
do
{
ModalDialog((ModalFilterProcPtr)ModalFilter, &itemHit);
}
while (itemHit != OK && itemHit != Cancel);
if (itemHit == OK)
{
GetIText((Handle) cntl[kItem_LineNum], s1); sscanf(PtoCstr(s1) , "%hd", &line_to_go);
PinValue(&line_to_go, 0, 32767);
}
DisposDialog(myDialog); myDialog = NULL;
if (itemHit == OK)
goto_line(line_to_go);
EnableItem(myMenus[1], 1); /* about box */
EnableItem(myMenus[fmn_ID], 0); /* File menu */
EnableItem(myMenus[edmn_ID], edmn_undo); /* undo */
DrawMenuBar();
}
void GetPreferences(void)
{
DialogPtr updatingDialog;
if (OpenPrefsFile() != noErr)
{
error_dialog(145);
exit_handler();
}
/* Get saved settings for Render Options dialog from the Prefs file */
theUpdateRgn = NewRgn();
UseResFile(prefsRefNum);
global_settings_h = (prefs_hdl_t) Get1Resource('DFLT', kSettings_rsrcID);
if (global_settings_h != NULL)
{
/* Is it the wrong version? */
if ((**global_settings_h).prefs_version != kSettings_vers)
{ /* old version, delete & create new one below! */
RmveResource((Handle)global_settings_h);
global_settings_h = NULL; /* flag code below to add new */
}
/* Still got it? Use it! */
if (global_settings_h != NULL)
{
MoveHHi((Handle) global_settings_h);
HLock((Handle) global_settings_h);
global_settings = *global_settings_h;
/* make sure our windows are visible on THIS MACHINE'S screens */
forceRectOnScreen(&global_settings->srcWind_pos);
forceRectOnScreen(&global_settings->statWind_pos);
forceRectOnScreen(&global_settings->imageWind_pos);
}
}
/* create a new one if can't read or use the old one */
if (global_settings_h == NULL)
{
TargetTicks = TICKS + 180L;
updatingDialog = GetNewDialog (147, NULL, (WindowPtr) -1);
if (updatingDialog)
DrawDialog(updatingDialog);
global_settings_h = (prefs_hdl_t) NewHandle(sizeof(prefs_rec_t));
if (global_settings_h == 0)
{
error_dialog(132);
exit_handler();
}
MoveHHi((Handle) global_settings_h);
HLock((Handle) global_settings_h);
global_settings = *global_settings_h;
global_settings->prefs_version = kSettings_vers;
SetRect(&global_settings->srcWind_pos,
8,
GetMBarHeight()+20,
min(600, qd.screenBits.bounds.right-40),
qd.screenBits.bounds.bottom-40);
SetRect(&global_settings->statWind_pos,
20, GetMBarHeight()+40,
480, 240);
SetRect(&global_settings->imageWind_pos,
8, GetMBarHeight()+20,
8, GetMBarHeight()+20);
global_settings->width = 320;
global_settings->height = 240;
global_settings->from = 0;
global_settings->to = 240;
global_settings->threshold = 0.30;
global_settings->quality = 9;
global_settings->howMultiFriendly = kDefMultiFriendly;
global_settings->cr_file = false;
global_settings->resume = false;
global_settings->antialias = false;
global_settings->ditherPaint = true;
global_settings->magniFactor = 1;
global_settings->request_shutdown = false;
strcpy(global_settings->paths,":::Include:\x0d::Include:\x0d");
UseResFile(prefsRefNum);
AddResource ((Handle) global_settings_h, 'DFLT', kSettings_rsrcID, "\pRender Options");
Write_Our_Prefs();
if (updatingDialog)
{
while (TICKS < TargetTicks)
{ };
DisposeDialog(updatingDialog);
updatingDialog = 0;
}
}
}
void GetFileSettings(void)
{
Handle tmpHandle;
SetVol(NULL, theVRefNum);
fileResRefNum = OpenResFile(theFileName);
if (fileResRefNum == -1)
{
CreateResFile(theFileName);
fileResRefNum = OpenResFile(theFileName);
if (fileResRefNum == -1)
return;
}
tmpHandle = Get1Resource ('SETT', kSettings_rsrcID);
if (tmpHandle != NULL)
{
/* delete old file_settings_h first! */
if (file_settings_h)
{
DisposeHandle((Handle)file_settings_h);
file_settings_h = NULL;
}
/* Is it the wrong version? */
if ((**(prefs_hdl_t)tmpHandle).prefs_version != kSettings_vers)
{ /* old version, delete & create new one below! */
RmveResource(tmpHandle);
tmpHandle = NULL; /* flag code below to add new */
}
/* Still got it? Use it! */
if (tmpHandle != NULL)
{
file_settings_h = (prefs_hdl_t) tmpHandle;
MoveHHi((Handle) file_settings_h);
HLock((Handle) file_settings_h);
file_settings = *file_settings_h; /* dereference handle */
/* make sure our windows are on THIS MACHINE'S screens */
forceRectOnScreen(&file_settings->srcWind_pos);
forceRectOnScreen(&file_settings->statWind_pos);
forceRectOnScreen(&file_settings->imageWind_pos);
}
}
/* create a new one if can't read or use the old one */
if (tmpHandle == NULL)
{
file_settings_h = (prefs_hdl_t) NewHandle(sizeof(prefs_rec_t));
MoveHHi((Handle) file_settings_h);
HLock((Handle) file_settings_h);
file_settings = *file_settings_h;
memcpy (file_settings, global_settings, sizeof(prefs_rec_t));
AddResource( (Handle) file_settings_h, 'SETT', kSettings_rsrcID,"\pPOV-Ray Settings");
UpdateResFile(fileResRefNum);
}
}
void WriteFileSettings(void)
{
if (fileResRefNum != -1)
{
UseResFile(fileResRefNum);
ChangedResource( (Handle) file_settings_h);
WriteResource( (Handle) file_settings_h);
UpdateResFile(fileResRefNum);
UseResFile(ourRefNum);
}
}
void CloseFileSettings(void)
{
if (fileResRefNum != -1)
CloseResFile(fileResRefNum);
fileResRefNum = -1;
}
#define kItem_gImageWidth 4
#define kItem_gImageHeight 5
#define kItem_gImageQuality 6
#define kItem_gAntiAliasCheck 7
#define kItem_gAntiAliasThreshold 8
#define kItem_gBgFriendlyCheck 9
#define kItem_gSearchPaths 11
void ChangeGlobalSettings(void)
{
short i, dummyInt, remember_Opts;
Rect displayRect;
ControlHandle cntl[31];
char s1[256];
HiliteMenu(0);
DisableItem(myMenus[1], 1); /* about box */
DisableItem(myMenus[fmn_ID], 0); /* File menu */
DisableItem(myMenus[edmn_ID], edmn_undo); /* Undo */
do_notify = 0; /* in case "Open" was selected before notification completed */
UseResFile(ourRefNum);
myDialog = GetNewDialog(146, NULL, (WindowPtr) -1);
remember_Opts = 0;
for (i = 1; i <= 12; i++)
GetDItem(myDialog, i, &dummyInt, (Handle *) &cntl[i], &displayRect);
sprintf(s1, "%d", global_settings->width);
SetIText((Handle) cntl[kItem_gImageWidth], CtoPstr(s1) );
sprintf(s1, "%d", global_settings->height);
SetIText((Handle) cntl[kItem_gImageHeight], CtoPstr(s1) );
sprintf(s1, "%d", global_settings->quality);
SetIText((Handle) cntl[kItem_gImageQuality], CtoPstr(s1) );
SetCtlValue(cntl[kItem_gAntiAliasCheck], global_settings->antialias);
sprintf(s1, "%.2f", global_settings->threshold);
SetIText((Handle) cntl[kItem_gAntiAliasThreshold], CtoPstr(s1) );
SetIText((Handle) cntl[kItem_gSearchPaths], CtoPstr(global_settings->paths) ); PtoCstr(global_settings->paths);
sprintf(s1, "%d", global_settings->howMultiFriendly);
SetIText((Handle) cntl[kItem_gBgFriendlyCheck], CtoPstr(s1) );
SelIText(myDialog, kItem_gImageWidth, 0, 32767);
/* "default" the OK button */
SetupDefaultButton(myDialog);
do
{
ModalDialog((ModalFilterProcPtr)ModalFilter, &itemHit);
if (itemHit == kItem_gAntiAliasCheck)
SetCtlValue(cntl[itemHit], !GetCtlValue(cntl[itemHit]));
enable_return_key = (itemHit != kItem_gSearchPaths);
}
while (itemHit != OK && itemHit != Cancel);
if (itemHit == OK)
{
GetIText((Handle) cntl[kItem_gImageWidth], s1); sscanf(PtoCstr(s1) , "%hd", &global_settings->width);
PinValue(&global_settings->width, 0, 4095);
GetIText((Handle) cntl[kItem_gImageHeight], s1); sscanf(PtoCstr(s1) , "%hd", &global_settings->height);
PinValue(&global_settings->height, 0, 4095);
global_settings->from = 0;
global_settings->to = global_settings->height;
GetIText((Handle) cntl[kItem_gImageQuality], s1); sscanf(PtoCstr(s1) , "%hd", &global_settings->quality);
global_settings->antialias = GetCtlValue(cntl[kItem_gAntiAliasCheck]);
GetIText((Handle) cntl[kItem_gBgFriendlyCheck], s1);
sscanf(PtoCstr(s1) , "%hd", &global_settings->howMultiFriendly);
PinValue(&global_settings->howMultiFriendly, kMinMultiFriendly, kMaxMultiFriendly);
MultiFriendly = global_settings->howMultiFriendly;
GetIText((Handle) cntl[kItem_gAntiAliasThreshold], s1); sscanf(PtoCstr(s1) , "%lf", &global_settings->threshold);
GetIText((Handle) cntl[kItem_gSearchPaths], global_settings->paths);
PtoCstr (global_settings->paths);
i = strlen(global_settings->paths);
if (global_settings->paths[i - 1] != 13)
{
global_settings->paths[i] = 13;
global_settings->paths[i + 1] = 0;
}
Write_Our_Prefs();
}
DisposDialog(myDialog); myDialog = NULL;
EnableItem(myMenus[1], 1); /* about box */
EnableItem(myMenus[fmn_ID], 0); /* File menu */
EnableItem(myMenus[edmn_ID], edmn_undo); /* undo */
DrawMenuBar();
}
#define kItem_fFilename 4
#define kItem_fImageWidth 5
#define kItem_fImageHeight 6
#define kItem_fRowFrom 7
#define kItem_fRowTo 8
#define kItem_fImageQuality 9
#define kItem_fAntiAliasCheck 10
#define kItem_fAntiAliasThreshold 11
#define kItem_fDoTargaCheck 12
#define kItem_fContinueTargaCheck 13
#define kItem_fBtnThumbnail 14
#define kItem_fBtnPreview 15
#define kItem_fBtnFullSize 16
void ChangeFileSettings(void)
{
DialogPtr myWarningDialog;
short i, dummyInt, remember_Opts;
Rect displayRect;
ControlHandle cntl[31];
char s1[256];
char pFname[256];
HiliteMenu(0);
DisableItem(myMenus[1], 1); /* about box */
DisableItem(myMenus[fmn_ID], 0); /* File menu */
DisableItem(myMenus[edmn_ID], edmn_undo); /* Undo */
do_notify = 0; /* in case "Open" was selected before notification completed */
strcpy (pFname, c_theFileName);
CtoPstr (pFname);
UseResFile(ourRefNum);
myDialog = GetNewDialog(128, NULL, (WindowPtr) -1);
remember_Opts = 0;
for (i = 1; i <= 23; i++)
GetDItem(myDialog, i, &dummyInt, (Handle *) &cntl[i], &displayRect);
SetIText((Handle) cntl[kItem_fFilename], pFname );
sprintf(s1, "%d", file_settings->width); SetIText((Handle) cntl[kItem_fImageWidth], CtoPstr(s1) );
sprintf(s1, "%d", file_settings->height); SetIText((Handle) cntl[kItem_fImageHeight], CtoPstr(s1) );
sprintf(s1, "%d", file_settings->from); SetIText((Handle) cntl[kItem_fRowFrom], CtoPstr(s1) );
sprintf(s1, "%d", file_settings->to); SetIText((Handle) cntl[kItem_fRowTo], CtoPstr(s1) );
sprintf(s1, "%d", file_settings->quality); SetIText((Handle) cntl[kItem_fImageQuality], CtoPstr(s1) );
SetCtlValue(cntl[kItem_fAntiAliasCheck], file_settings->antialias);
sprintf(s1, "%.2f", file_settings->threshold); SetIText((Handle) cntl[kItem_fAntiAliasThreshold], CtoPstr(s1) );
SetCtlValue(cntl[kItem_fDoTargaCheck], file_settings->cr_file);
SetCtlValue(cntl[kItem_fContinueTargaCheck], file_settings->resume);
SelIText(myDialog, kItem_fImageWidth, 0, 32767);
/* "default" the OK button */
SetupDefaultButton(myDialog);
do
{
ModalDialog((ModalFilterProcPtr)ModalFilter, &itemHit);
switch (itemHit)
{
case kItem_fAntiAliasCheck: /* anti-alias */
SetCtlValue(cntl[itemHit], !GetCtlValue(cntl[itemHit]));
break;
case kItem_fDoTargaCheck: /* Create Targa file */
SetCtlValue(cntl[itemHit], !GetCtlValue(cntl[itemHit]));
if (GetCtlValue(cntl[itemHit]) == 0)
SetCtlValue(cntl[kItem_fContinueTargaCheck],0); /* no Targa, no Resume. */
break;
case kItem_fContinueTargaCheck: /* Resume interrupted scan */
SetCtlValue(cntl[itemHit], !GetCtlValue(cntl[itemHit]));
if (GetCtlValue(cntl[itemHit]))
SetCtlValue(cntl[kItem_fDoTargaCheck],1); /* must have output file option */
break;
case kItem_fBtnThumbnail: /* Thumbnail */
SetCtlValue(cntl[kItem_fDoTargaCheck], 0); /* output file option */
SetCtlValue(cntl[kItem_fContinueTargaCheck],0); /* Resume option */
SetCtlValue(cntl[kItem_fAntiAliasCheck], 0); /* Antialias? */
SetIText((Handle) cntl[kItem_fImageWidth], "\p32"); /* width */
SetIText((Handle) cntl[kItem_fImageHeight], "\p32"); /* height */
SetIText((Handle) cntl[kItem_fRowFrom], "\p0"); /* From */
SetIText((Handle) cntl[kItem_fRowTo], "\p32"); /* To */
SetIText((Handle) cntl[kItem_fImageQuality],"\p9"); /* Quality */
SelIText(myDialog, kItem_fImageQuality, 0, 32767); /* select quality */
break;
case kItem_fBtnPreview: /* 320 x 240 Preview */
SetCtlValue(cntl[kItem_fDoTargaCheck], 0); /* output file option */
SetCtlValue(cntl[kItem_fContinueTargaCheck],0); /* Resume option */
SetCtlValue(cntl[kItem_fAntiAliasCheck], 0); /* Antialias? */
SetIText((Handle) cntl[kItem_fImageWidth], "\p320"); /* width */
SetIText((Handle) cntl[kItem_fImageHeight], "\p240"); /* height */
SetIText((Handle) cntl[kItem_fRowFrom], "\p0"); /* From */
SetIText((Handle) cntl[kItem_fRowTo], "\p240"); /* To */
SetIText((Handle) cntl[kItem_fImageQuality],"\p9"); /* Quality */
if (file_settings->magniFactor > 2)
file_settings->magniFactor = 2;
SelIText(myDialog, kItem_fImageQuality, 0, 32767); /* select "quality" text */
break;
case kItem_fBtnFullSize: /* High Quality */
SetCtlValue(cntl[kItem_fDoTargaCheck], 1); /* output file option */
SetCtlValue(cntl[kItem_fAntiAliasCheck], 1); /* Antialias? */
SetIText((Handle) cntl[kItem_fImageWidth], "\p640"); /* width */
SetIText((Handle) cntl[kItem_fImageHeight], "\p480"); /* height */
SetIText((Handle) cntl[kItem_fRowFrom], "\p0"); /* From */
SetIText((Handle) cntl[kItem_fRowTo], "\p480"); /* To */
SetIText((Handle) cntl[kItem_fImageQuality],"\p9"); /* Quality */
SetIText((Handle) cntl[kItem_fAntiAliasThreshold],"\p0.1"); /* Antialias amount */
SelIText(myDialog, kItem_fAntiAliasThreshold, 0, 32767); /* select anti-alias amount */
if (file_settings->magniFactor > 1)
file_settings->magniFactor = 1;
break;
}
}
while (itemHit != OK && itemHit != Cancel);
if (itemHit != Cancel)
{
GetIText((Handle) cntl[kItem_fImageWidth], s1); sscanf(PtoCstr(s1) , "%hd", &file_settings->width);
PinValue(&file_settings->width, 0, 4095);
GetIText((Handle) cntl[kItem_fImageHeight], s1); sscanf(PtoCstr(s1) , "%hd", &file_settings->height);
PinValue(&file_settings->height, 0, 4095);
GetIText((Handle) cntl[kItem_fRowFrom], s1); sscanf(PtoCstr(s1) , "%hd", &file_settings->from);
PinValue(&file_settings->from, 0, file_settings->height);
GetIText((Handle) cntl[kItem_fRowTo], s1); sscanf(PtoCstr(s1) , "%hd", &file_settings->to);
PinValue(&file_settings->to, file_settings->from, file_settings->height);
GetIText((Handle) cntl[kItem_fImageQuality], s1); sscanf(PtoCstr(s1) , "%hd", &file_settings->quality);
file_settings->antialias = GetCtlValue(cntl[kItem_fAntiAliasCheck]);
GetIText((Handle) cntl[kItem_fAntiAliasThreshold], s1); sscanf(PtoCstr(s1) , "%lf", &file_settings->threshold);
file_settings->cr_file = GetCtlValue(cntl[kItem_fDoTargaCheck]);
file_settings->resume = GetCtlValue(cntl[kItem_fContinueTargaCheck]);
if ( ((file_settings->to) < (file_settings->height)) || (file_settings->from) )
{
UseResFile(ourRefNum);
myWarningDialog = GetNewDialog(131, NULL, (WindowPtr) -1);
if (myWarningDialog)
{
/* "default" the OK button */
SetupDefaultButton(myWarningDialog);
do
ModalDialog(NULL, &itemHit);
while (itemHit != OK && itemHit != Cancel);
if (itemHit == Cancel)
{
file_settings->to = file_settings->height;
file_settings->from = 0;
}
DisposDialog(myWarningDialog);
}
}
WriteFileSettings();
}
DisposDialog(myDialog); myDialog = NULL;
EnableItem(myMenus[1], 1); /* about box */
EnableItem(myMenus[fmn_ID], 0); /* File menu */
EnableItem(myMenus[edmn_ID], edmn_undo); /* undo */
DrawMenuBar();
}
void Render(void)
{
char s1[256], s2[256], *s2_p, *s3_p, c;
int i;
ARGC = 0;
argptr = argstr;
AddArg("POV");
AddArg("+d0");
AddArg("-p");
AddArg("+ms500");
/* option-Render will be verbose */
if (myEvent.modifiers & optionKey)
AddArg("+v");
AddArg("-x");
sprintf(s1, "-w%d", file_settings->width); AddArg(s1);
sprintf(s1, "-h%d", file_settings->height); AddArg(s1);
sprintf(s1, "-s%d", file_settings->from); AddArg(s1);
sprintf(s1, "-e%d", file_settings->to); AddArg(s1);
if (file_settings->antialias)
{
sprintf(s1, "+a%.3f", file_settings->threshold);
AddArg(s1);
}
else
AddArg("-a");
sprintf(s1, "-q%d", file_settings->quality); AddArg(s1);
if (file_settings->cr_file)
AddArg("+ft");
else
AddArg("-f");
AddArg(file_settings->resume ? "+c" : "-c");
sprintf(s1, "-i%s", c_theFileName); AddArg(s1);
strcpy(s2, c_theFileName);
if (strstr(s2, ".POV"))
{
i = strlen(s2);
s2[i - 4] = 0;
}
if (file_settings->cr_file)
{
strcat(s2, ".tga");
strcpy(targaOutName, s2);
sprintf(s1, "-o%s", s2); AddArg(s1);
}
/* Add -l options for library paths. */
strcpy(s2, global_settings->paths);
c = *s2;
s3_p = s2_p = s2;
while (c)
{
while (*s3_p && *s3_p != 13)
s3_p++;
c = *s3_p;
*s3_p = 0;
/* Remove trailing ':'; POV takes care of appending that. */
if (*(s3_p - 1) == ':')
*(s3_p - 1) = 0;
if (*s2_p)
{
sprintf(s1, "-l%s", s2_p);
AddArg(s1);
}
s2_p = ++s3_p;
}
SetVol(NULL, theVRefNum);
Stop_Flag = 0;
run_flag = 1;
}
void ChangeTargaType(void)
{
OSErr i;
FInfo myFileInfo;
if (file_settings->cr_file)
{
CtoPstr(targaOutName);
i = GetFInfo (targaOutName, theVRefNum, &myFileInfo);
if (i==0)
{
myFileInfo.fdType = 'TPIC';
myFileInfo.fdCreator = '8BIM';
i = SetFInfo (targaOutName, theVRefNum, &myFileInfo);
}
PtoCstr(targaOutName);
}
}
void inval_port_rect(void)
{
Rect myInvalRect;
if (plot_window)
{
SetPort(plot_window);
myInvalRect.top = 0;
myInvalRect.bottom = display_magniFactor * (global_y + 1);
myInvalRect.left = 0;
myInvalRect.right = display_magniFactor * global_width;
InvalRect(&myInvalRect);
}
}
/* post-processing */
void make_undo(void)
{
if (undo_buffer == 0)
{
undo_buffer = NewPtr (global_bufsize); /* room for image */
undo_buffer2 = NewPtr (global_bufsize); /* room for image */
revert_buffer = NewPtr (global_bufsize);
if ( (revert_buffer) && (plot_pixmap))
memcpy (revert_buffer, plot_pixmap, global_bufsize);
}
/* if any of the memory allocations failed, or available mem is low, fail the whole undo system */
if ( (undo_buffer == 0) || (undo_buffer2 == 0) ||
(revert_buffer == 0) || (FreeMem() < 20000L) )
{
if (undo_buffer) DisposePtr (undo_buffer);
if (undo_buffer2) DisposePtr (undo_buffer2);
if (revert_buffer) DisposePtr (revert_buffer);
undo_buffer = 0;
undo_buffer2 = 0;
revert_buffer = 0;
}
if ((undo_buffer) && (plot_pixmap))
{
memcpy (undo_buffer, plot_pixmap, global_bufsize);
undoable = TRUE;
}
}
void undo(void)
{
if ((undo_buffer) && (undoable) && (plot_pixmap))
{
memcpy (undo_buffer2, plot_pixmap, global_bufsize);
memcpy (plot_pixmap, undo_buffer, global_bufsize);
memcpy (undo_buffer, undo_buffer2, global_bufsize);
inval_port_rect();
}
}
void revert_image(void)
{
if ((revert_buffer) && (plot_pixmap))
{
memcpy (undo_buffer, plot_pixmap, global_bufsize);
memcpy (plot_pixmap, revert_buffer, global_bufsize);
undoable = TRUE;
inval_port_rect();
}
}
short clipped_value(short v)
{
if ( v < 0)
return (0);
if (v > 255)
return (255);
return (v);
}
void darken_image(void)
{
unsigned char *pptr;
long i,j;
make_undo();
if (plot_pixmap == 0) return;
for (i=0; i < global_height; i++)
{
for (j=0; j < global_width; j++)
{
pptr = (unsigned char *)
(plot_pixmap + 4L * ((global_width * i) + j));
*pptr = 0;
pptr++;
*pptr = (*pptr * 7 / 8);
pptr++;
*pptr = (*pptr * 7 / 8);
pptr++;
*pptr = (*pptr * 7 / 8);
pptr++;
}
}
inval_port_rect();
}
void lighten_image(void)
{
unsigned char *pptr;
long i,j;
short v;
make_undo();
if (plot_pixmap == 0) return;
for (i=0; i < global_height; i++)
{
for (j=0; j < global_width; j++)
{
pptr = (unsigned char *)
(plot_pixmap + 4L * ((global_width * i) + j));
*pptr = 0;
pptr++;
v = (*pptr * 8 / 7);
*pptr = clipped_value (v);
pptr++;
v = (*pptr * 8 / 7);
*pptr = clipped_value (v);
pptr++;
v = (*pptr * 8 / 7);
*pptr = clipped_value (v);
pptr++;
}
}
inval_port_rect();
}
void invert_image(void)
{
unsigned char *pptr;
long i,j;
make_undo();
if (plot_pixmap == 0) return;
for (i=0; i < global_height; i++)
{
for (j=0; j < global_width; j++)
{
pptr = (unsigned char *)
(plot_pixmap + 4L * ((global_width * i) + j));
*pptr = 0;
pptr++;
*pptr = 255 - *pptr;
pptr++;
*pptr = 255 - *pptr;
pptr++;
*pptr = 255 - *pptr;
pptr++;
}
}
inval_port_rect();
}
void reduce_contrast(void)
{
unsigned char *pptr;
long i,j;
short v;
make_undo();
if (plot_pixmap == 0) return;
for (i=0; i < global_height; i++)
{
for (j=0; j < global_width; j++)
{
pptr = (unsigned char *)
(plot_pixmap + 4L * ((global_width * i) + j));
*pptr++ = 0;
v = *pptr;
v = v - ((v - 128) / 4);
*pptr++ = v;
v = *pptr;
v = v - ((v - 128) / 4);
*pptr++ = v;
v = *pptr;
v = v - ((v - 128) / 4);
*pptr++ = v;
}
}
inval_port_rect();
}
void increase_contrast(void)
{
unsigned char *pptr;
long i,j;
short v;
make_undo();
if (plot_pixmap == 0) return;
for (i=0; i < global_height; i++)
{
for (j=0; j < global_width; j++)
{
pptr = (unsigned char *)
(plot_pixmap + 4L * ((global_width * i) + j));
*pptr++ = 0;
v = *pptr;
v = v + ((v - 128) / 4);
*pptr++ = clipped_value(v);
v = *pptr;
v = v + ((v - 128) / 4);
*pptr++ = clipped_value(v);
v = *pptr;
v = v + ((v - 128) / 4);
*pptr++ = clipped_value(v);
}
}
inval_port_rect();
}
/* draw a black border around the edge of the image */
void draw_border(void)
{
unsigned char *pptr;
long i;
make_undo();
if (plot_pixmap == 0) return;
for (i=0; i < global_height; i++)
{
/* left border edge */
pptr = (unsigned char *)
(plot_pixmap + (global_width * 4 * i) );
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
/* right border edge */
pptr = (unsigned char *)
(plot_pixmap + (global_width * 4 * i) + ((global_width-1) * 4) );
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
}
for (i=0; i < global_width; i++)
{
/* top border edge */
pptr = (unsigned char *)
(plot_pixmap + (4 * i));
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
/* bottom border edge */
pptr = (unsigned char *)
( plot_pixmap + 4L*global_width*(global_height-1) + 4*i );
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
*pptr++ = 0;
}
inval_port_rect();
}
void AboutPOV(void)
{
Str31 appVers, compilerName;
UseResFile(ourRefNum);
myDialog = GetNewDialog(130, NULL, (WindowPtr) -1);
if (myDialog)
{
GetAppVersionPString(1, appVers);
GetCompilerNamePString(compilerName);
ParamText(appVers, compilerName, "", "");
/* Get into dialog's port & fiddle with fonts.. */
SetPort((GrafPtr)myDialog);
TextFont(geneva);
TextSize(9);
ShowWindow((WindowPtr)myDialog);
/* "default" the OK button */
SetupDefaultButton(myDialog);
do
ModalDialog(NULL, &itemHit);
while (itemHit != 1);
TextFont(geneva);
TextSize(9);
DisposDialog(myDialog);
}
myDialog = NULL;
}
void DisableMenus(void)
{
int i;
for (i = 2; i <= highest_menu; i++)
DisableItem(myMenus[i], 0);
DisableItem(myMenus[1], 1);
DrawMenuBar();
}
void EnableMenus(void)
{
int i;
for (i = 2; i <= highest_menu; i++)
EnableItem(myMenus[i], 0);
EnableItem(myMenus[1], 1);
DrawMenuBar();
}
void UpdateMenus(void)
{
short i;
if (qd32_Available)
EnableItem(myMenus[omn_ID], omn_dither);
else
DisableItem(myMenus[omn_ID], omn_dither);
/* Set the checking status of the "Options" menu */
CheckItem(myMenus[omn_ID], omn_dither, (file_settings->ditherPaint && qd32_Available));
CheckItem(myMenus[omn_ID], omn_shutdown, file_settings->request_shutdown);
/* Mark up the the WindowSize menu */
CheckItem(mySubMenus[viewmn_ID],1,display_magniFactor == 0);
CheckItem(mySubMenus[viewmn_ID],2,display_magniFactor == 1);
CheckItem(mySubMenus[viewmn_ID],3,display_magniFactor == 2);
CheckItem(mySubMenus[viewmn_ID],4,display_magniFactor == 3);
CheckItem(mySubMenus[viewmn_ID],5,display_magniFactor == 4);
CheckItem(mySubMenus[viewmn_ID],6,display_magniFactor == 5);
/* Enable individual Windows menu items */
if (myp2windowIsUp)
EnableItem(myMenus[wndmn_ID], 1);
else
DisableItem(myMenus[wndmn_ID], 1);
if (window_visible)
EnableItem(myMenus[wndmn_ID], 2);
else
DisableItem(myMenus[wndmn_ID], 2);
if (plot_window)
EnableItem(myMenus[wndmn_ID], 3);
else
DisableItem(myMenus[wndmn_ID], 3);
/* Enable the Edit menu */
DisableItem(myMenus[edmn_ID], edmn_undo);
DisableItem(myMenus[edmn_ID], edmn_cut);
DisableItem(myMenus[edmn_ID], edmn_copy);
DisableItem(myMenus[edmn_ID], edmn_paste);
DisableItem(myMenus[edmn_ID], edmn_clear);
DisableItem(myMenus[edmn_ID], edmn_redo);
DisableItem(myMenus[edmn_ID], edmn_goto);
if (FrontWindow() == TextEditWindow)
{
EnableItem(myMenus[edmn_ID], edmn_goto);
if ((**TEH).selStart != (**TEH).selEnd)
{
EnableItem(myMenus[edmn_ID], edmn_cut);
EnableItem(myMenus[edmn_ID], edmn_copy);
EnableItem(myMenus[edmn_ID], edmn_clear);
}
EnableItem(myMenus[edmn_ID], edmn_paste);
if (undo_record[max_undo].reason[0])
EnableItem(myMenus[edmn_ID], edmn_undo);
if (redo_record[max_undo].reason[0])
EnableItem(myMenus[edmn_ID], edmn_redo);
}
if (FrontWindow() == plot_window)
{
if (undoable)
EnableItem(myMenus[edmn_ID], edmn_undo);
if (plot_pixmap)
EnableItem(myMenus[edmn_ID], edmn_copy);
}
/* Enable the WindowSize menu */
if ((plot_pixmap) || (global_y < (global_height / 25)) || (run_flag == 0))
{
EnableItem(mySubMenus[viewmn_ID],1);
EnableItem(mySubMenus[viewmn_ID],2);
EnableItem(mySubMenus[viewmn_ID],3);
EnableItem(mySubMenus[viewmn_ID],4);
EnableItem(mySubMenus[viewmn_ID],5);
EnableItem(mySubMenus[viewmn_ID],6);
}
else
{
/* don't let the user destroy his window unintentionally in the special case:
/* memory's so low that there's no pixmap for refresh */
for (i=1; i <= 6; i++)
DisableItem(mySubMenus[viewmn_ID], i);
}
/* Enable the Image enhancement menu items */
if ((plot_pixmap) && (virtual_file == 0) && (run_flag == 0))
for (i=immn_border; i <= immn_revert; i++)
EnableItem(myMenus[immn_ID], i);
else
for (i=immn_border; i <= immn_revert; i++)
DisableItem(myMenus[immn_ID], i);
/* specifically disable the separator lines */
DisableItem(myMenus[immn_ID],immn_divider1);
DisableItem(myMenus[immn_ID],immn_divider2);
DisableItem(myMenus[immn_ID],immn_divider3);
/* Enable File Menu items */
if ((plot_window != 0) || (window_visible == TRUE))
EnableItem(myMenus[fmn_ID], fmn_close); /* Close */
else
DisableItem(myMenus[fmn_ID],fmn_close);
if (myDialog == 0)
{
if (POV_running)
{
if (FrontWindow() == TextEditWindow)
DisableItem(myMenus[2], fmn_close); /* don't allow close during render */
DisableItem(myMenus[1], 1); /* about box */
DisableItem(myMenus[fmn_ID], fmn_open); /* Open file */
DisableItem(myMenus[fmn_ID], fmn_new); /* New file */
DisableItem(myMenus[fmn_ID], fmn_render); /* Render */
DisableItem(myMenus[fmn_ID], fmn_newopts); /* new options */
if ((window_visible) && (FrontWindow() == TextEditWindow) && (dirty))
EnableItem(myMenus[fmn_ID], fmn_savetext); /* Save is okay */
else
DisableItem(myMenus[fmn_ID], fmn_savetext);
DisableItem(myMenus[fmn_ID], fmn_saveas); /* Save as╔ */
EnableItem(myMenus[fmn_ID], fmn_pause); /* pause trace */
EnableItem(myMenus[fmn_ID], fmn_stop); /* abort trace */
DisableItem(myMenus[fmn_ID], fmn_savepict); /* Save output as╔ */
}
else
{
EnableItem(myMenus[1], 1); /* about box */
DisableItem(myMenus[fmn_ID], fmn_render); /* Render */
DisableItem(myMenus[fmn_ID], fmn_newopts); /* new options */
if (window_visible)
{
EnableItem(myMenus[fmn_ID], fmn_saveas); /* Save as╔ */
if (c_theFileName[0])
{
EnableItem(myMenus[fmn_ID], fmn_newopts); /* new options */
EnableItem(myMenus[fmn_ID], fmn_render); /* Render */
}
}
else
{
DisableItem(myMenus[2], fmn_saveas); /* Save as╔ */
}
if ((window_visible) && (dirty))
{
EnableItem(myMenus[fmn_ID], fmn_savetext); /* Save */
DisableItem(myMenus[fmn_ID], fmn_new); /* New file */
DisableItem(myMenus[fmn_ID], fmn_open); /* Open file */
}
else
{
EnableItem(myMenus[fmn_ID], fmn_new); /* New file */
EnableItem(myMenus[fmn_ID], fmn_open); /* Open file */
DisableItem(myMenus[fmn_ID], fmn_savetext); /* Save */
}
DisableItem(myMenus[fmn_ID], fmn_pause); /* pause trace */
DisableItem(myMenus[fmn_ID], fmn_stop); /* abort trace */
if ((plot_pixmap) && (display_magniFactor))
EnableItem(myMenus[fmn_ID], fmn_savepict); /* Save output as╔ */
else
DisableItem(myMenus[fmn_ID], fmn_savepict);
}
}
}
void ask_about_quit(void)
{
if ( (file_settings->cr_file == 0) && (run_flag) )
{
UseResFile(ourRefNum);
myDialog = GetNewDialog (137, NULL, (WindowPtr) -1);
/* "default" the OK button */
SetupDefaultButton(myDialog);
do
{
ModalDialog(NULL, &itemHit);
if (itemHit == 1)
Stop_Flag = quit_flag = 1;
}
while (itemHit != 1 && itemHit != 2);
DisposDialog (myDialog); myDialog = NULL;
}
else
Stop_Flag = quit_flag = 1;
}
void ask_about_stop(void)
{
UseResFile(ourRefNum);
if (file_settings->cr_file)
myDialog = GetNewDialog (135, NULL, (WindowPtr) -1);
else
myDialog = GetNewDialog (134, NULL, (WindowPtr) -1);
/* "default" the OK button */
SetupDefaultButton(myDialog);
do
{
ModalDialog(NULL, &itemHit);
if (itemHit == 1)
Stop_Flag = 1;
if ((itemHit == 2) && (file_settings->cr_file))
itemHit = 3;
}
while (itemHit != 1 && itemHit != 2);
DisposDialog (myDialog); myDialog = NULL;
}
void pause_it(void)
{
if (pause_flag == 1)
pause_flag = 2;
else
{
pause_flag = 1;
HiliteMenu(0);
DisableItem(myMenus[1], 1); /* about box */
DisableItem(myMenus[edmn_ID], 0); /* Edit menu */
DisableItem(myMenus[omn_ID], 0); /* Options menu */
CheckItem(myMenus[2],fmn_pause,1);
do
MacDawdle();
while ((Stop_Flag == 0) && (pause_flag != 2));
EnableItem(myMenus[1], 1); /* about box */
EnableItem(myMenus[edmn_ID], 0); /* Edit menu */
EnableItem(myMenus[omn_ID], 0); /* Options menu */
CheckItem(myMenus[2],fmn_pause,0);
DrawMenuBar();
pause_flag = 0;
}
}
void Activate(WindowPtr theWindow)
{
/* Show the window controls */
if (theWindow)
{
SelectWindow(theWindow);
if (theWindow == TextEditWindow)
{
TEActivate(TEH);
ShowControl(vScroll);
TEFromScrap();
}
}
}
void Deactivate(WindowPtr theWindow)
{
/* Hide the window controls */
if ((theWindow == TextEditWindow) && (TextEditWindow != 0))
{
TEDeactivate(TEH);
HideControl(vScroll);
ZeroScrap();
TEToScrap();
}
}
OSErr MyDirID2VrefNum(short vRefNum, long dirID, short *theWDVrefNumPtr)
{
OSErr anError;
// Open a Working directory for ourselves. Note that we leave
// it open forever (just like SFGetFile does.) This is supposed
// to be kosher..
anError = OpenWD(vRefNum, dirID, kAppSignature, theWDVrefNumPtr);
return anError;
}
void OpenTextFile(Str255 fn, short vRef, long dirID, Boolean UseDirID)
{
short refNum;
Rect oldHorizBar;
Rect r;
int errcode = noErr;
/* If ODOC, find working dir from vref/dirID so we can use FSOpen etc. */
if (UseDirID)
{
/* convert vref/dirID into WD vrefnum for later FSOpen and SetVol calls */
errcode = MyDirID2VrefNum(vRef, dirID, &theVRefNum);
}
else
{
theVRefNum = vRef;
}
if (errcode==noErr)
errcode = FSOpen(fn, theVRefNum, &refNum);
if (errcode==noErr)
{
flush_undo_system();
errcode = ReadFile(refNum, TEH);
if (errcode == 1)
{
pStrCopy(fn, theFileName);
PtoCstr(theFileName);
strcpy(c_theFileName, (char *) theFileName);
CtoPstr(theFileName);
SetWTitle(TextEditWindow, theFileName);
dirty = 0;
}
if (errcode == 999)
FileError("\pFile too large to be edited: ", fn);
FSClose(refNum); /* and ignore close errors */
if (errcode == 1)
{
GetFileSettings();
SetPort(TextEditWindow);
// JIM! What is this oldHorizBar code for? Shouldn't this be AFTER we resize the window?
// doesn't the later InvalRect() code force a complete window update anyway?
// Eduard! Beats me! I'm just a victim of monkey-see monkey-do.
oldHorizBar = TextEditWindow->portRect;
oldHorizBar.top = oldHorizBar.bottom - (SBarWidth+1);
SizeWindow(TextEditWindow,
file_settings->srcWind_pos.right-file_settings->srcWind_pos.left,
file_settings->srcWind_pos.bottom-file_settings->srcWind_pos.top, false);
MoveWindow(TextEditWindow,
file_settings->srcWind_pos.left,
file_settings->srcWind_pos.top, false);
InvalRect(&TextEditWindow->portRect);
SetView(TextEditWindow);
EraseRect(&oldHorizBar);
MoveControl(vScroll, TextEditWindow->portRect.right - SBarWidth,
TextEditWindow->portRect.top-1);
SizeControl(vScroll, SBarWidth+1,
TextEditWindow->portRect.bottom - TextEditWindow->portRect.top-(SBarWidth-2));
r = (**vScroll).contrlRect;
ValidRect(&r);
AdjustText();
ShowWindow(TextEditWindow);
window_visible = TRUE;
TESetSelect(0, 0, TEH);
ShowSelect();
SelectWindow(TextEditWindow);
}
}
else
FileError("\pError opening ", fn);
EnableItem(myMenus[1], 1); /* about box */
EnableItem(myMenus[2], 0); /* File menu */
EnableItem(myMenus[edmn_ID], edmn_undo); /* undo */
DrawMenuBar();
}
short free_undo_memory(void)
{
short i;
/* from the oldest to newest (except the last), dispose the Undo & redo buffers */
for (i = 0; i < max_undo; i++)
{
if (redo_record[i].buf_handle)
{
DisposeHandle(redo_record[i].buf_handle);
redo_record[i].buf_handle = 0;
redo_record[i].reason[0] = 0;
return (1);
}
if (undo_record[i].buf_handle)
{
DisposeHandle(undo_record[i].buf_handle);
undo_record[i].buf_handle = 0;
undo_record[i].reason[0] = 0;
return (1);
}
}
return (0);
}
/* Support undo by duplicating the current file's text as necessary */
void support_undo(char *the_reason, short flush_redo)
{
int i;
char *buffer;
/* new changes are being made to the file. Redo no longer makes sense. */
if (flush_redo)
flush_redo_system();
/* Dispose oldest undo record storage, because the record will be destroyed. */
if (undo_record[0].buf_handle)
DisposeHandle(undo_record[0].buf_handle);
/* block-move the records down to make room for a new undo entry */
for (i = 0; i < max_undo; i++)
undo_record[i] = undo_record[i+1];
/* Try repeatedly to allocate memory for the undo buffer, disposing old */
/* undo buffers as necessary. */
TRY_AGAIN:
undo_record[max_undo].buf_handle = (char **) NewHandle((**TEH).teLength);
if (undo_record[max_undo].buf_handle == 0)
if (free_undo_memory()) goto TRY_AGAIN;
if (undo_record[max_undo].buf_handle == 0)
{
undo_record[max_undo].reason[0] = 0;
return;
}
HLock(undo_record[max_undo].buf_handle);
buffer = *(undo_record[max_undo].buf_handle);
undo_record[max_undo].selStart = (**TEH).selStart;
undo_record[max_undo].selEnd = (**TEH).selEnd;
strcpy(undo_record[max_undo].reason, the_reason);
strcpy(undo_menu_name, "Undo ");
strcat(undo_menu_name, the_reason);
CtoPstr(undo_menu_name);
SetItem(myMenus[edmn_ID], edmn_undo, undo_menu_name);
undo_record[max_undo].byteCount = (**TEH).teLength;
undo_record[max_undo].dirty = dirty;
memcpy(buffer, *(**TEH).hText, (**TEH).teLength);
HUnlock(undo_record[max_undo].buf_handle);
undo_key_copied = 0;
}
/* Support redo by duplicating the current file's text as necessary */
void support_redo(char *the_reason)
{
int i;
char *buffer;
/* Dispose oldest redo record storage, because the record will be destroyed. */
if (redo_record[0].buf_handle)
DisposeHandle(redo_record[0].buf_handle);
/* block-move the records down to make room for a new redo entry */
for (i = 0; i < max_undo; i++)
redo_record[i] = redo_record[i+1];
/* Try repeatedly to allocate memory for the redo buffer, disposing old */
/* redo buffers as necessary. */
TRY_AGAIN:
redo_record[max_undo].buf_handle = (char **) NewHandle((**TEH).teLength);
if (redo_record[max_undo].buf_handle == 0)
if (free_undo_memory()) goto TRY_AGAIN;
if (redo_record[max_undo].buf_handle == 0)
{
redo_record[max_undo].reason[0] = 0;
return;
}
HLock(redo_record[max_undo].buf_handle);
buffer = *(redo_record[max_undo].buf_handle);
redo_record[max_undo].selStart = (**TEH).selStart;
redo_record[max_undo].selEnd = (**TEH).selEnd;
strcpy(redo_record[max_undo].reason, the_reason);
strcpy(redo_menu_name, "Redo ");
strcat(redo_menu_name, the_reason);
CtoPstr(redo_menu_name);
SetItem(myMenus[edmn_ID], edmn_redo, redo_menu_name);
redo_record[max_undo].byteCount = (**TEH).teLength;
redo_record[max_undo].dirty = dirty;
memcpy(buffer, *(**TEH).hText, (**TEH).teLength);
HUnlock(redo_record[max_undo].buf_handle);
}
void support_undo_key(void)
{
if (undo_key_copied == 0)
{
support_undo("Typing", TRUE);
undo_key_copied = 1;
}
}
void undo_text()
{
int i;
char *buffer;
if (undo_record[max_undo].reason[0])
{
support_redo(undo_record[max_undo].reason);
(**TEH).selStart = 0;
(**TEH).selEnd = (**TEH).teLength;
TEDelete(TEH);
HLock(undo_record[max_undo].buf_handle);
buffer = *(undo_record[max_undo].buf_handle);
TEInsert(buffer, undo_record[max_undo].byteCount, TEH);
undo_key_copied = 0;
TESetSelect(undo_record[max_undo].selStart, undo_record[max_undo].selEnd, TEH);
dirty = undo_record[max_undo].dirty;
InvalRect(&TextEditWindow->portRect);
/* dispose of the current undo record's data */
DisposeHandle(undo_record[max_undo].buf_handle);
/* move other undo records up the chain. */
for (i = max_undo; i > 0; i--)
undo_record[i] = undo_record[i-1];
/* Delete the contents of the (duplicated) last record */
undo_record[0].buf_handle = 0;
undo_record[0].reason[0] = 0;
/* show everyone what the next undoable item will be */
strcpy(undo_menu_name, "Undo ");
strcat(undo_menu_name, undo_record[max_undo].reason);
CtoPstr(undo_menu_name);
SetItem(myMenus[edmn_ID], edmn_undo, undo_menu_name);
}
}
void redo_text()
{
int i;
char *buffer;
if (redo_record[max_undo].reason[0])
{
support_undo(redo_record[max_undo].reason, FALSE);
(**TEH).selStart = 0;
(**TEH).selEnd = (**TEH).teLength;
TEDelete(TEH);
HLock(redo_record[max_undo].buf_handle);
buffer = *(redo_record[max_undo].buf_handle);
TEInsert(buffer, redo_record[max_undo].byteCount, TEH);
undo_key_copied = 0;
TESetSelect(redo_record[max_undo].selStart, redo_record[max_undo].selEnd, TEH);
dirty = redo_record[max_undo].dirty;
/* dispose of the current undo record's data */
DisposeHandle(redo_record[max_undo].buf_handle);
/* move other undo records up the chain. */
for (i = max_undo; i > 0; i--)
redo_record[i] = redo_record[i-1];
/* Delete the contents of the (duplicated) last record */
redo_record[0].buf_handle = 0;
redo_record[0].reason[0] = 0;
/* show everyone what the next redoable item will be */
strcpy(redo_menu_name, "Redo ");
strcat(redo_menu_name, redo_record[max_undo].reason);
CtoPstr(redo_menu_name);
SetItem(myMenus[edmn_ID], edmn_redo, redo_menu_name);
}
}
void init_undo_system()
{
int i;
for (i = 0; i <= max_undo; i++)
{
undo_record[i].buf_handle = 0;
undo_record[i].reason[0] = 0;
}
undo_key_copied = 0;
}
void flush_undo_system()
{
int i;
for (i = 0; i <= max_undo; i++)
{
if (undo_record[i].buf_handle)
{
DisposeHandle(undo_record[i].buf_handle);
undo_record[i].buf_handle = 0;
}
undo_record[i].reason[0] = 0;
}
undo_key_copied = 0;
}
void init_redo_system()
{
int i;
for (i = 0; i <= max_undo; i++)
{
redo_record[i].buf_handle = 0;
redo_record[i].reason[0] = 0;
}
}
void flush_redo_system()
{
int i;
for (i = 0; i <= max_undo; i++)
{
if (redo_record[i].buf_handle)
{
DisposeHandle(redo_record[i].buf_handle);
redo_record[i].buf_handle = 0;
}
redo_record[i].reason[0] = 0;
}
}
void DoFile_New(void)
{
if ((run_flag == 0) && (window_visible == FALSE))
{
SetWTitle(TextEditWindow, "\pUntitled");
ShowWindow(TextEditWindow);
window_visible = TRUE;
dirty = 0;
}
} // DoFile_New
void DoFile_Open(void)
{
short vRef;
Str255 fn;
if (run_flag == 0)
if (OldFile(fn, &vRef))
OpenTextFile(fn, vRef, 0L, false/*!UseDirID*/);
} // DoFile_Open
void DoFileMenu(short theItem)
{
switch (theItem)
{
case fmn_new: /* New File */
DoFile_New();
break;
case fmn_open: /* Open a file */
DoFile_Open();
break;
case fmn_close: /* Close */
if (FrontWindow() == plot_window)
{
DisposeWindow(plot_window);
plot_window = NULL;
display_magniFactor = 0;
}
else if (FrontWindow() == TextEditWindow)
{
DoFile(fmn_close);
}
break;
case fmn_savetext: /* Save */
if ((TextEditWindow) && (window_visible))
{
DoFile(fmn_savetext);
/* set up c string to enable other menu options */
PtoCstr(theFileName);
strcpy(c_theFileName, (char *) theFileName);
CtoPstr(theFileName);
WriteFileSettings();
}
break;
case fmn_saveas: /* Save as╔ */
DoFile(fmn_saveas);
/* set up c string to enable other menu options */
PtoCstr(theFileName);
strcpy(c_theFileName, (char *) theFileName);
CtoPstr(theFileName);
GetFileSettings();
break;
case fmn_render: /* Render */
DoFile(fmn_render);
if (c_theFileName)
{
if (myp2window)
{
ShowWindow((WindowPtr)myp2window);
myp2windowIsUp = true;
SelectWindow((WindowPtr)myp2window);
}
Render();
}
break;
case fmn_newopts: /* Change options */
if ((run_flag == 0) && (fileResRefNum != -1) && (window_visible))
ChangeFileSettings();
break;
case fmn_pause: /* pause trace */
pause_it();
break;
case fmn_stop: /* Abort trace in progress? */
ask_about_stop();
break;
case fmn_savepict: /* Save output as╔ */
saveOutputFile(true);
break;
case fmn_prefs:
ChangeGlobalSettings();
break; /* Preferences╔ */
case fmn_quit:
if (DoFile(fmn_close))
ask_about_quit();
break; /* Quit the program */
}
}
void DoEditMenu(short theItem)
{
if (SystemEdit(theItem-1) != 0)
return;
/* Edit menu for dialogs */
if (myDialog)
{
switch (theItem)
{
case edmn_cut: DlgCut(myDialog); break;
case edmn_copy: DlgCopy(myDialog); break;
case edmn_paste: DlgPaste(myDialog); break;
case edmn_clear: DlgDelete(myDialog); break;
}
}
/* Edit menu for text editor */
if (FrontWindow() == TextEditWindow)
{
switch (theItem)
{
case edmn_undo:
undo_text();
AdjustText();
break;
case edmn_cut:
support_undo("Cut", TRUE);
TECut(TEH);
AdjustText();
dirty = 1;
break;
case edmn_copy:
TECopy(TEH);
break;
case edmn_paste:
support_undo("Paste", TRUE);
TEPaste(TEH);
AdjustText();
dirty = 1;
break;
case edmn_clear:
support_undo("Clear", TRUE);
TEDelete(TEH);
AdjustText();
dirty = 1;
break;
case edmn_redo:
redo_text();
AdjustText();
break;
case edmn_goto:
choose_goto_line();
}
}
/* Edit menu for output image window */
if (FrontWindow() == plot_window)
{
switch (theItem)
{
case edmn_undo:
if (undoable) /*undo*/
undo();
break;
case edmn_copy:
if (plot_pixmap) /*copy*/
paint_to_picture(FALSE);
break;
}
}
}
void DoCommand(long m)
{
short theMenu, theItem;
Str255 name;
Rect brect;
theMenu = (m >> 16) - 127;
theItem = m;
switch (theMenu)
{
case 1:
if (theItem == 1)
AboutPOV();
else
{
GetItem(myMenus[1], theItem, name);
OpenDeskAcc(name);
}
break;
case 2:
DoFileMenu(theItem);
break;
case 3:
DoEditMenu(theItem);
break;
case 4:
switch (theItem)
{
case omn_dither:
file_settings->ditherPaint = !file_settings->ditherPaint;
inval_port_rect();
break;
case omn_shutdown:
file_settings->request_shutdown = !file_settings->request_shutdown;
if ((run_flag) && (file_settings->request_shutdown))
error_dialog(148);
}
break;
case 200-128+viewmn_ID:
file_settings->magniFactor = theItem - 1;
if (myDialog == 0)
{
display_magniFactor = file_settings->magniFactor;
if (display_magniFactor == 5)
display_magniFactor = 8;
if (plot_window)
DisposeWindow(plot_window);
plot_window = NULL;
if ( (display_magniFactor) && (plot_pixmap) )
{
SetRect(&disp_plot_bounds, 0, 0,
global_width * display_magniFactor,
global_height * display_magniFactor);
brect = disp_plot_bounds;
OffsetRect(&brect,
file_settings->imageWind_pos.left,
file_settings->imageWind_pos.top);
plot_window = NewCWindow(NULL, &brect, theFileName, true,
noGrowDocProc, (WindowPtr) -1L, false, 0);
}
}
break;
case immn_ID:
switch (theItem)
{
case immn_border: draw_border(); break;
case immn_darken: darken_image(); break;
case immn_lighten: lighten_image(); break;
case immn_reduceC: reduce_contrast(); break;
case immn_increaseC: increase_contrast(); break;
case immn_invert: invert_image(); break;
case immn_revert: revert_image(); break;
}
break;
case wndmn_ID: /* Windows menu */
switch (theItem)
{
case 1: if (myp2windowIsUp)
{
SelectWindow((WindowPtr)myp2window);
}
break;
case 2: if ((TextEditWindow) && (window_visible))
{ /* be thorough */
ShowWindow(TextEditWindow);
SelectWindow(TextEditWindow);
}
break;
case 3: if (plot_window)
{
SelectWindow(plot_window);
}
break;
}
break;
}
HiliteMenu(0);
}
void DoMouseDown(void)
{
short code, part;
WindowPtr whichWindow;
ControlHandle whichControl;
Rect theWindowPos;
code = FindWindow(myEvent.where, &whichWindow);
if ((whichWindow == TextEditWindow) && (whichWindow != 0))
DoEditMouseDown (code, whichWindow, &myEvent);
else
{
switch (code)
{
case inMenuBar:
SetCursor(&qd.arrow);
UpdateMenus();
DoCommand(MenuSelect(myEvent.where));
break;
case inSysWindow:
SystemClick(&myEvent, whichWindow);
break;
case inGoAway:
if (TrackGoAway(whichWindow, myEvent.where))
;
break;
case inGrow:
if ((whichWindow == (WindowPtr)myp2window) && (myp2window))
{
p2w_DoGrow(myp2window, &myEvent);
get_WindowPos((WindowPtr)myp2window, &theWindowPos);
global_settings->statWind_pos = theWindowPos;
}
break;
case inZoomIn:
case inZoomOut:
if (TrackBox(whichWindow, myEvent.where, code))
;
break;
case inDrag:
DragWindow(whichWindow, myEvent.where, &dragBounds);
get_WindowPos(whichWindow, &theWindowPos);
if ((whichWindow == (WindowPtr)myp2window) && (myp2window))
global_settings->statWind_pos = theWindowPos;
if ((whichWindow == plot_window) && (plot_window))
{
global_settings->imageWind_pos = theWindowPos;
file_settings->imageWind_pos = theWindowPos;
}
break;
case inContent:
if (whichWindow != FrontWindow())
SelectWindow(whichWindow);
else
{
if ((whichWindow == (WindowPtr)myp2window) && (myp2window))
p2w_DoContentClick(myp2window, &myEvent);
else
if (whichWindow == plot_window)
{
SetPort(whichWindow);
GlobalToLocal(&myEvent.where);
part = FindControl(myEvent.where, whichWindow, &whichControl);
/* perform window controls such as resizing or scrolling here */
}
}
break;
}
}
}
void DoKeyDown(void)
{
char theChar, theVirtualCode;
theChar = myEvent.message & charCodeMask;
theVirtualCode = (myEvent.message & keyCodeMask) >> 8;
if (myEvent.modifiers & cmdKey)
{
UpdateMenus();
DoCommand(MenuKey(theChar));
}
else
{
if (FrontWindow() == TextEditWindow)
{
switch (theVirtualCode)
{
case 0x33: /* delete */
if ((**TEH).selStart != (**TEH).selEnd)
{
support_undo("Delete", TRUE);
TEDelete(TEH); /* delete a range */
}
else
{
support_undo_key();
TEKey(theChar, TEH); /* delete char */
}
dirty = 1;
AdjustText();
break;
case 0x73: /* HOME */
SetCtlValue(vScroll, 0);
AdjustText();
break;
case 0x77: /* END */
SetCtlValue(vScroll, (**TEH).teLength);
AdjustText();
break;
case 0x74: /* PAGE UP */
ScrollProc(vScroll, inPageUp);
AdjustText();
break;
case 0x79: /* PAGE DOWN */
ScrollProc(vScroll, inPageDown);
AdjustText();
break;
case 0x7A: /* UNDO (F1) */
undo_text();
break;
case 0x78: /* CUT (F2) */
support_undo("Cut", TRUE);
TECut(TEH);
AdjustText();
dirty = 1;
break;
case 0x63: /* COPY (F3) */
TECopy(TEH);
break;
case 0x76: /* PASTE (F4) */
support_undo("Paste", TRUE);
TEPaste(TEH);
AdjustText();
dirty = 1;
break;
case 0x75: /* del >x> */
if ((**TEH).selStart != (**TEH).selEnd)
{
support_undo("Delete", TRUE);
TEDelete(TEH);
AdjustText();
}
else
{ /* cursor-right then delete */
support_undo_key();
TEKey(0x1D, TEH);
TEKey(0x08, TEH);
}
dirty = 1;
break;
case 0x1C: /* Cursor keys, don't dirty the buffer or require undo */
case 0x1D:
case 0x1E:
case 0x1F:
TEKey(theChar, TEH);
ShowSelect();
break;
default: /* all other keys */
support_undo_key();
TEKey(theChar, TEH);
dirty = 1;
ShowSelect();
}
}
}
}
void DoUpdateEvt(void)
{
WindowPtr wnd;
wnd = (WindowPtr) myEvent.message;
if ((wnd == TextEditWindow) && (TextEditWindow != 0))
UpdateWindow (wnd);
else
if ((wnd == (WindowPtr) myp2window) && (myp2window))
p2w_DoUpdate(myp2window);
else
{ /* update the display window */
BeginUpdate(wnd);
SetPort(wnd);
if ( (wnd == plot_window) && (plot_window) )
{
SetPort(plot_window);
paint_whole_window();
}
EndUpdate(wnd);
}
}
void DoActivateEvt(void)
{
if (((WindowPtr)myEvent.message == (WindowPtr)myp2window) && (myp2window))
p2w_DoActivate(myp2window, myEvent.modifiers & 1);
else
if (myEvent.modifiers & 1)
Activate((WindowPtr) myEvent.message);
else
Deactivate((WindowPtr) myEvent.message);
}
void DoApp4Evt(void)
{
if (myEvent.message >> 24 == 1)
{
/* Update the background-friendliness flag upon Suspend/Resume */
MultiFriendly = global_settings->howMultiFriendly;
if (myEvent.message & 1)
{
backgrounding = 0;
Activate(FrontWindow());
}
else
{
backgrounding = TRUE;
Deactivate(FrontWindow());
/* If in the background, back off on the rendering throttle some */
if (MultiFriendly > 2)
MultiFriendly -= (MultiFriendly >> 1);
}
SetCursor(&qd.arrow);
}
}
void DoHighLevelEvt(void)
{
short i;
if (myEvent.message == 'aevt'/*kCoreEventClass*/)
i = AEProcessAppleEvent(&myEvent);
/* AppleEvents are the only supported high level events */
}
void MacDawdle(void)
{
int evtresult;
if (backgrounding == 0)
{
// Stuff that only gets done if we're in front.
if (TextEditWindow)
{
SetPort(TextEditWindow);
MaintainCursor();
if (TEH)
TEIdle(TEH);
}
}
if (WNEavailable)
{
if (run_flag)
WaitNextEvent(everyEvent, &myEvent, 0, NULL);
else
{
SetEventMask(everyEvent);
WaitNextEvent(everyEvent, &myEvent, 10, NULL);
}
}
else
{
SystemTask();
evtresult = GetNextEvent(everyEvent, &myEvent);
}
switch (myEvent.what)
{
case mouseDown:
if (startupScreen)
{
DisposDialog (startupScreen);
startupScreen = NULL;
startupMessageTime = 0;
}
DoMouseDown();
break;
case keyDown:
case autoKey:
if (startupScreen)
{
DisposDialog (startupScreen);
startupScreen = NULL;
startupMessageTime = 0;
}
DoKeyDown();
break;
case updateEvt: DoUpdateEvt(); break;
case activateEvt: DoActivateEvt(); break;
case app4Evt: DoApp4Evt(); break;
case kHighLevelEvent: /* high level event */
DoHighLevelEvt(); break;
/* case nullEvent: DoNullEvt(); */
}
}
void DialogDawdle(void)
{
int evtresult;
short isMyDialog;
char theChar;
itemHit = 0;
if (WNEavailable)
WaitNextEvent(everyEvent, &myEvent, 15, NULL);
else
evtresult = GetNextEvent(everyEvent, &myEvent);
isMyDialog = IsDialogEvent (&myEvent);
if (isMyDialog)
DialogSelect (&myEvent,&myDialog,&itemHit);
else
{
itemHit = 0;
switch (myEvent.what)
{
case mouseDown:
DoMouseDown();
break;
case keyDown:
theChar = myEvent.message & charCodeMask;
if (myEvent.modifiers & cmdKey)
DoKeyDown();
break;
case updateEvt: DoUpdateEvt(); break;
case activateEvt: DoActivateEvt(); break;
case app4Evt: DoApp4Evt(); break;
case nullEvent:
break;
case kHighLevelEvent: /* high level event */
DoHighLevelEvt(); break;
}
}
}
void exit_handler(void)
{
delete_virtual();
if (myp2window)
p2w_DisposeWindow(myp2window);
p2w_Terminate();
if (fileResRefNum != -1)
CloseResFile (fileResRefNum);
if ((prefsRefNum != -1) && global_settings_h)
{
UseResFile(prefsRefNum);
Write_Our_Prefs();
UseResFile(ourRefNum);
CloseResFile (prefsRefNum);
prefsRefNum = -1;
}
if (gtheSCComponent != NULL)
{
CloseComponent(gtheSCComponent);
gtheSCComponent = NULL;
}
quit_flag = 1;
ExitToShell();
}
void unexpected_exit(void)
{
if (quit_flag == 0)
{
if (global_settings_h)
{
DisposeHandle((Handle) global_settings_h);
global_settings_h = NULL;
}
if (plot_window)
{
SetPort(plot_window);
paint_whole_window();
}
error_dialog(132);
exit_handler();
}
}
void notify_user(void)
{
Handle the_snd_handle;
OSErr myErr;
/* If the image rendered OK and shutdown was requested, then shut down. */
if ((file_settings->request_shutdown) && (rendered_OK))
{
saveOutputFile(false); /* write PICT file with current name.PICT */
dispose_virtual(); /* close virtual file */
if (AppleEvents_Available)
SendQuit();
else
ShutDwnPower();
}
else
do_notify = TRUE;
/* Play sound effect if in background, to get everyone's attention. */
if (backgrounding)
{
the_snd_handle = GetNamedResource('snd ',"\pFileDone");
if (the_snd_handle)
myErr = SndPlay(NULL, the_snd_handle, TRUE);
}
}
main()
{
long stk_size, start_ticks;
int i;
Handle h;
CTabHandle ctH;
SysEnvRec theWorld;
OSErr anError;
StringPtr errStr;
Rect p2wRect;
#ifdef applec
UnloadSeg((Ptr) _DataInit);
#endif applec
ourRefNum = CurResFile();
/* Allocate more memory for stack. */
h = Get1Resource('CNFG', 128);
if (h)
{
stk_size = ** ((long **) h);
ReleaseResource(h);
}
else
stk_size = 40000; /* a reasonable stack limit? */
SetApplLimit(GetApplLimit() - stk_size);
MaxApplZone();
/* give us some master pointer blocks ahead of time, to reduce later memfrag */
for (i=0; i<10; i++)
MoreMasters();
/* Register an exit handler */
atexit(unexpected_exit);
/* Initialize toolbox managers. */
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(NULL);
InitCursor();
SetCursor(&qd.arrow);
i=EventAvail(0, &myEvent);
i=EventAvail(0, &myEvent);
i=EventAvail(0, &myEvent);
/* pre-allocate spare RAM for dialogs, which tend to pop up for out-of-memory conditions. */
extra_dialog_RAM = NewHandle(reserveMemSize);
prev_upd_plot = myEvent.when;
/* Check if the necessary hard- & software is present. */
errStr = NULL;
SysEnvirons(1, &theWorld);
WNEavailable = trapAvailable(_WaitNextEvent, OSTrap, &theWorld);
Gestalt_Available = true;
qd32_Available = trapAvailable(_QD32Trap, ToolTrap, &theWorld);
if (theWorld.processor < env68020)
errStr = "\pThis software requires a 68020 or better CPU.";
if (!theWorld.hasFPU)
errStr = "\pThis software requires a Floating Point Unit.";
if (theWorld.systemVersion < 0x0604)
errStr = "\pThis software requires System 6.0.4 or better";
if (!qd32_Available)
errStr = "\pThis software requires 32 Bit Quickdraw";
if (errStr)
{
ParamText(errStr, "", "", "");
StopAlert(129, NULL);
exit_handler();
}
/* set up bounds for window dragging (multiple/big monitors) */
SetRect(&dragBounds, -32000, -32000, 32000, 32000);
/* display splash screen early on, while app gets set up */
startupMessageTime = TICKS;
startupScreen = GetNewDialog(138, NULL, (WindowPtr) -1);
if (startupScreen == NULL)
startupMessageTime = 0;
else
{
Str31 appVers, compilerName;
GetAppVersionPString(1, appVers);
GetCompilerNamePString(compilerName);
ParamText(appVers, compilerName, "", "");
DrawDialog(startupScreen);
}
/* See if the image compression manager (QuickTime to the Rest Of Us) is installed. */
ImageCompressionMgrAvailable = false;
if (Gestalt_Available)
{
long gestaltResponse;
if (Gestalt(gestaltCompressionMgr, &gestaltResponse) == noErr)
if (gestaltResponse >= 15)
{
/* Install and open the standard compression dialog component. */
gtheSCComponent = OpenStdCompression();
if (gtheSCComponent != NULL)
{
ImageCompressionMgrAvailable = true;
/* Initial defaults for SC compression dialog. */
gSCDialogParams.flags = 0;
gSCDialogParams.theCodecType = 'jpeg';
gSCDialogParams.theCodec = anyCodec;
gSCDialogParams.spatialQuality = codecNormalQuality;
gSCDialogParams.temporalQuality = 0;
gSCDialogParams.depth = 32;
}
}
}
/* Set up menus. */
for (i = 1; i <= highest_menu; i++)
{
myMenus[i] = GetMenu(i + 127);
if (myMenus[i] == 0) exit_handler();
}
for (i = 1; i <= highest_submenu; i++)
{
mySubMenus[i] = GetMenu(i + 199);
if (mySubMenus[i] == 0) exit_handler();
}
AddResMenu(myMenus[1], 'DRVR');
for (i = 1; i <= highest_menu; i++)
InsertMenu(myMenus[i], 0);
for (i = 1; i <= highest_submenu; i++)
InsertMenu(mySubMenus[i], -1);
DrawMenuBar();
GetPreferences();
/* refresh splash screen in case previous dialogs walked on it */
if (startupScreen)
DrawDialog(startupScreen);
/* create a default file settings record now. */
file_settings_h = (prefs_hdl_t) NewHandle(sizeof(prefs_rec_t));
MoveHHi((Handle) file_settings_h);
HLock((Handle) file_settings_h);
file_settings = *file_settings_h;
memcpy (file_settings, global_settings, sizeof(prefs_rec_t));
/* Re-default to the application's resource file for other functions like dialogs. */
UseResFile(ourRefNum);
*theFileName = 0;
fileResRefNum = -1;
/* Set up the status output window */
anError = p2w_Init();
if (!anError)
{
p2wRect = global_settings->statWind_pos;
myp2window = p2w_NewWindow(&p2wRect, "\pPOV Status", false, monaco, 9, &anError);
}
if (anError)
{
error_dialog(kdlog_P2W_INIT_ERROR);
exit_handler();
}
/* Set up offscreen pixmap. */
ctH = (CTabHandle) NewHandle(sizeof(ColorTable));
(*ctH)->ctSeed = 24;
(*ctH)->ctFlags = 0;
(*ctH)->ctSize = 0;
pm = (PixMapHandle) NewHandle(sizeof(PixMap));
(*pm)->pmVersion = 0;
(*pm)->packType = 0;
(*pm)->packSize = 0;
(*pm)->hRes = 0x480000;
(*pm)->vRes = 0x480000;
(*pm)->pixelType = RGBDirect;
(*pm)->pixelSize = 32;
(*pm)->cmpCount = 3;
(*pm)->cmpSize = 8;
(*pm)->planeBytes = 0;
(*pm)->pmTable = ctH;
(*pm)->pmReserved = 0;
init_undo_system();
init_redo_system();
Install_AppleEvents();
maxmalloc = FreeMem() / 210L;
GarbagePile = (long *) NewPtr(maxmalloc*4L + 8L);
RecycledPile = (long *) NewPtr(maxmalloc*4L + 8L);
if ((GarbagePile == 0) || (RecycledPile == 0))
{ StopAlert(129, NULL);
exit_handler(); }
*GarbagePile = 0; /* unmark first item on list */
*RecycledPile = 0;
mallocCount = 0;
mfreeCount = 0;
rendered_OK = 1;
/* Figure out how much time to give other processes */
MultiFriendly = global_settings->howMultiFriendly;
main_init(); /* for text editor */
/* Main event loop, sort of. */
while (!quit_flag)
{
MacDawdle();
/* Check for notification of finished trace */
if (do_notify && (backgrounding == 0))
{
for (i=1; i<3; i++)
MacDawdle(); /* get update events */
if (do_notify)
error_dialog (143 - rendered_OK);
do_notify = 0;
}
/* Check for timeout on startup message. Remove the dialog after timeout. */
if (startupScreen)
if ( (startupMessageTime) && ((startupMessageTime+420) < TICKS) )
{
DisposDialog (startupScreen);
startupScreen = NULL;
startupMessageTime = 0;
}
/* Update current settings for the magnification factor for display window */
display_magniFactor = file_settings->magniFactor;
if (display_magniFactor == 5)
display_magniFactor = 8;
if (run_flag)
{
Size toGrow;
if (file_settings->request_shutdown)
error_dialog (148);
/* open some heap space just before we start */
MaxMem(&toGrow);
start_ticks = TICKS;
#ifdef NEEDS_PERF
printf("Starting performance analysis\n");
startPerf();
#endif NEEDS_PERF
call_main(ARGC, ARGV);
#ifdef NEEDS_PERF
stopPerf();
printf("Completed performance analysis\n");
#endif NEEDS_PERF
/* if it was a long, uninterrupted trace, OR if POV is in the background, OR if shutdown
was requested at completion, OR there was an error, call the notification procedure. */
if (
(Stop_Flag == 0) &&
(((TICKS - start_ticks) > 7200) || backgrounding
|| file_settings->request_shutdown || (rendered_OK == 0))
)
notify_user();
}
else
if (quit_flag) break;
}
/* Clean up & exit. */
exit_handler();
}